【问题标题】:Outlook Addin: Working with threadsOutlook 插件:使用线程
【发布时间】:2013-05-06 12:14:54
【问题描述】:

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

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

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

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

有人对如何在 Outlook 插件中使用后台线程有一些指导吗?

【问题讨论】:

    标签: outlook vsto outlook-addin outlook-redemption


    【解决方案1】:

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

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

    【讨论】:

    • 这是一个示例不工作的代码,它会导致 Outlook 崩溃:gist.github.com/saguiitay/5565244
    • 尝试使用 {} 来确定 RDOSession 变量的范围并调用 GC.Collect();毕竟所有 RDO 对象都超出了范围。
    【解决方案2】:

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

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

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

    3. 使用完之后立即对您使用的每个 COM 对象使用“Marshal.ReleaseComObject”。这可能是导致不稳定的原因,因为 Outlook 真的不喜欢它的对象留得太久。例如这行代码“var table = rdoFolder.Items.MAPITable;”创建两个 COM 对象:RDOItems 和 MAPITable,它们都必须释放,因此您需要拆分此行以保存对 RDOItems 对象的引用。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-16
      相关资源
      最近更新 更多