2013-05-12 79 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