2013-05-12 63 views
4

我正在處理Outlook加載項,並且必須處理大量項目。這需要花費很多時間,因此我試圖讓處理在不同的線程中運行(使用Task.Factory.StartNew)。但是,這導致Outlook隨機崩潰。Outlook加載項:使用線程

我正在使用Redemption與MAPITable一起工作,以減少工作量並只加載相關數據。

  • 我試着從我的主線程和我的工作線程初始化我的RDOSession。
  • 我試着讓主線程的MAPIFolders,並且只用MAPITable的工作線程工作

目前,這對我的作品的唯一事情是運行在主線程我所有的邏輯(在按鈕點擊事件中),但是這會長時間鎖定Outlook的用戶界面,這從用戶的角度來看是不可接受的。

有沒有人有一些關於如何使用Outlook Addin中的後臺線程的指針?

回答

3

有在我的項目類似的代碼,我建議如下:

  1. 使用Thread類創建新的線程,並設置它的公寓STA。

  2. 使用「session.Logon(」profileName「,NoMail:true,NewSession:false)登錄會話;」而不是使用MAPIOBJECT。我發現它比使用MAPIOBJECT有更好的性能,我的猜測是它仍然將一些調用封送回主線程,因爲在主線程上創建了MAPIOBJECT。

  3. 使用「Marshal.ReleaseComObject」在您使用它們後立即使用的每個COM對象上。這可能是導致不穩定的原因,因爲當對象被遺留太久時,Outlook真的不喜歡。例如,這行代碼「var table = rdoFolder.Items.MAPITable;」創建兩個COM對象:RDOItems和MAPITable,它們都必須被釋放,所以你需要分割這一行以保存對RDOItems對象的引用。

  4. 呼叫GC.CollectApplication.DoEvents,因爲如果你不叫Marshal.ReleaseComObject的所有COM對象的終結將嘗試釋放它們,將掛起,因爲創建的COM對象的線程不泵消息循環,它的終結器方法必須在創建它們的線程上運行。

  5. 如果可以,請啓動輔助進程並在單獨的進程中執行此循環。這將使用戶界面和後臺工作之間最大程度的分離。

1

在輔助線程中使用RDO對象時出現了什麼問題?只要在輔助線程上創建RDOSession,就應該正確初始化MAPI。

此外,TaskFactory使用線程池,您最好使用顯式的Thread類,o至少確保RDOSession不在不同線程之間共享 - 必須在每個線程上初始化MAPI。

+0

下面是一個示例的非工作的代碼,這導致在Outlook崩潰:https://gist.github.com/saguiitay/5565244 – SaguiItay 2013-05-12 22:49:16

+0

使用嘗試範圍RDOSession變量{}和調用GC.Collect();畢竟RDO對象超出了範圍。 – 2013-05-14 16:44:25