2016-01-21 23 views
2

我的C#VSTO Outlook 2010 AddIn將數百個MAPI文件夾異步添加到導入的pst文件。 (PST在Outlook foldertree存在)Outlook 2010 VSTO AddIn:UI隨意凍結,同時向PST異步添加文件夾

下面是一個例子:

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); 
}); 

觀UI在rootFolder.Folders.Add(...)隨機凍結2-3秒。有時在20之後,有時在50個添加文件夾之後。

任何幫助/提示將不勝感激。

回答

2

期望您的插件在Outlook 2013或更新版本中完全停止工作:OOM一旦檢測到它是從主Outlook線程以外的線程調用,就會報錯。請注意,這僅適用於COM插件,因爲它們在outlook.exe地址空間內運行。 COM系統總是將外部進程訪問封送到主Outlook線程中(但是這違背了從單獨線程使用OOM的全部目的)。

只能在輔助線程上使用擴展MAPI(C++或Delphi)。如果使用Redemption是一個選項(可以使用包括C#的任何語言),則其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); 
} 
+0

+1寫這篇詳細的提示。我正在考慮使用C++/cli和IMAPIFolder :: CreateFolder(..)。如果失敗,你的回答將被接受,我會購買你的贖回圖書館。 – eWilli

+0

我設法讓它使用C++/cli和擴展MAPI。 [見MSDN](https://msdn.microsoft.com/en-us/library/office/cc815501.aspx)。速度的差異是驚人的。對於不熟悉託管C++的人,我建議使用Redemption!接受的答案。 – eWilli