Outlook 2010 VSTO 加载项:UI 随机冻结,同时异步将文件夹添加到 PST
本文关键字:异步 文件夹 添加 PST 加载项 VSTO 2010 UI 冻结 随机 Outlook | 更新日期: 2023-09-27 18:31:12
My C# VSTO Outlook 2010 AddIn 将数百个 MAPI 文件夹异步添加到导入的 pst 文件中。(pst 存在于 Outlook 文件夹树中)
下面是一个示例:
Task.Factory.StartNew(() => {
... //get pstStore
var rootFolder = pstStore.GetRootFolder();
for (int i = 0; i < 500; i++)
{
var folder = rootFolder.Folders.Add("Test" + DateTime.Now.Ticks);
Thread.SpinWait(1000); //emulate work
Marshal.ReleaseComObject(folder);
}
Marshal.ReleaseComObject(rootFolder);
});
Outlook UI 在 rootFolder.Folders.Add(...)
时随机冻结 2-3 秒。有时在 20 个之后,有时在 50 个添加文件夹之后。
任何帮助/提示将不胜感激。
预计您的加载项将在 Outlook 2013 或更高版本中完全停止工作:OOM 在检测到从主 Outlook 线程以外的线程调用时,会立即引发错误。请注意,这仅适用于 COM 加载项,因为它们在 outlook.exe 地址空间内运行时。进程外访问始终由 COM 系统封送到主 Outlook 线程(但这违背了从单独线程使用 OOM 的全部目的)。
只能在辅助线程上使用扩展 MAPI(C++ 或 Delphi)。如果可以选择使用 Redemption(可以从任何语言(包括 C# - 我是它的作者)使用),则可以在辅助线程上使用其 RDO 系列对象:将 Namespace.MAPIOBJECT
属性的值存储在主线程(它是 MAPI 接口IMAPISession
),然后在辅助线程上创建RDOSession
对象的实例(将在该线程上初始化 MAPI),并将 RDOSession.MAPIOBJECT
属性设置为存储在主线程上的值 - 这样,两者将共享相同的 MAPI 会话。
在我的头顶上:
object mapiObject; //on the class/global level
..
mapiObject = Application.Session.MAPIOBJECT;
...
Task.Factory.StartNew(() => {
Redemption.RDOSession session = new Redemption.RDOSession();
session.MAPIOBJECT = mapiObject;
Redemption.RDOStore pstStore = session.Stores["YourStoreName"];
Redemption.RDOFolder rootFolder = pstStore.IPMRootFolder;
Redemption.RDOFolders folders = rootFolder.Folders;
for (int i = 0; i < 500; i++)
{
var folder = folders.Add("Test" + DateTime.Now.Ticks);
Marshal.ReleaseComObject(folder);
}
Marshal.ReleaseComObject(folders);
Marshal.ReleaseComObject(rootFolder);
Marshal.ReleaseComObject(session);
}