Outlook插件:处理线程



我正在使用Outlook插件,我必须处理大量项目。这需要花费相当多的时间,因此我尝试在不同的线程中运行该处理(使用Task.Factory.StartNew)。但是,这会导致Outlook随机崩溃。

我正在使用Redemption与MAPITable一起工作,以减少工作量并只加载相关数据。

  • 我已经尝试从主线程和工作线程初始化我的RDOSession。
  • 我试过在主线程上获得MAPIFolders,并且只在工作线程上使用MAPITable

目前,对我来说唯一有效的是在主线程上运行我的所有逻辑(在按钮单击事件中),但是这会锁定Outlook的用户界面很长一段时间,这从用户的角度来看是不可接受的。

有没有人有一些指针如何工作与后台线程从Outlook插件?

在我的项目中有类似的代码,我建议如下:

  1. 使用thread类创建新线程并将其设置为STA

  2. 使用"session"登录到会话。登录("profileName", NoMail: true, NewSession: false);"并且不使用MAPIOBJECT。我发现它比使用MAPIOBJECT有更好的性能,我的猜测是它仍然封送一些回调到主线程,因为MAPIOBJECT是在主线程上创建的。

  3. 使用"元帅。在你使用完每一个COM对象后,立即释放它们。这可能是造成不稳定的原因,因为Outlook真的不喜欢它的对象放置太久。例如,这行代码"var table = rdoFolder.Items.MAPITable;"创建了两个COM对象:RDOItems和MAPITable,它们都必须被释放,所以你需要拆分这行来保存对RDOItems对象的引用。

  4. 调用GC。收集和申请。DoEvents,因为如果你不调用Marshal。在所有COM对象上的ReleaseComObject,终结器将尝试释放它们并挂起,因为COM对象是在没有泵消息循环的线程上创建的,并且它的终结器方法必须在创建它们的线程上运行。

  5. 如果可以,启动一个辅助进程,并在单独的进程中执行此循环。这将使UI和后台工作之间最大限度的分离。

在辅助线程中使用RDO对象有什么问题?只要在辅助线程上创建了RDOSession,就应该正确初始化MAPI。

同样,TaskFactory使用线程池,你最好使用一个显式的thread类,至少要确保RDOSession不是在不同的线程之间共享的——MAPI必须在每个线程上初始化。

最新更新