6

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

我正在使用 Redemption 来处理 MAPITable,以减少工作量并仅加载相关数据。

  • 我尝试从我的主线程和我的工作线程初始化我的 RDOSession。
  • 我尝试在主线程上获取 MAPIFolders,并在工作线程上仅使用 MAPITable

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

是否有人对如何从 Outlook 插件中使用后台线程有一些指示?

4

2 回答 2

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,因为如果您不对所有 COM 对象调用 Marshal.ReleaseComObject,终结器将尝试释放它们并将挂起,因为 COM 对象是在不泵送消息循环的线程上创建的,并且它是终结器方法必须在创建它们的线程上运行。

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

于 2013-05-13T14:46:44.017 回答
1

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

此外,TaskFactory 使用线程池,最好使用显式 Thread 类,至少确保 RDOSession 不在不同线程之间共享 - 必须在每个线程上初始化 MAPI。

于 2013-05-12T19:48:44.510 回答