Outlook 2010 VSTO 加载项:UI 随机冻结,同时将文件夹异步添加到 PST
Outlook 2010 VSTO AddIn: UI freezes randomly, while adding folders to PST asynchronously
我的 C# VSTO Outlook 2010 加载项将数百个 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 地址 space 内。 Out-of-proc 访问总是由 COM 系统编组到主 Outlook 线程(但这违背了从单独线程使用 OOM 的全部目的)。
只能在辅助线程上使用扩展 MAPI(C++ 或 Delphi)。如果使用 Redemption is an option (it can be used from any language including C# - I am its author), its RDO family of objects 可以在辅助线程上使用:将 Namespace.MAPIOBJECT
属性 的值存储在主线程上(它是 IMAPISession
MAPI 接口),然后在辅助线程上创建 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);
}
我的 C# VSTO Outlook 2010 加载项将数百个 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 地址 space 内。 Out-of-proc 访问总是由 COM 系统编组到主 Outlook 线程(但这违背了从单独线程使用 OOM 的全部目的)。
只能在辅助线程上使用扩展 MAPI(C++ 或 Delphi)。如果使用 Redemption is an option (it can be used from any language including C# - I am its author), its RDO family of objects 可以在辅助线程上使用:将 Namespace.MAPIOBJECT
属性 的值存储在主线程上(它是 IMAPISession
MAPI 接口),然后在辅助线程上创建 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);
}