【问题标题】:VSTO Background Threading with STA and COM带有 STA 和 COM 的 VSTO 后台线程
【发布时间】:2013-07-28 14:05:36
【问题描述】:

我正在构建一个 VSTO 加载项:我需要运行一个后台线程,但该线程需要访问 COM 组件(我已实现 IMessageFilter 以使此消息传递尽可能安全)。我相信所有访问 OLE 或 COM 的线程都必须是 STA;因此,BackgroundWorker 不在讨论范围内。

我很高兴使用普通线程并将 ApartmentState 设置为 STA,但我还需要知道该线程何时完成,以便更新一些 UI 内容。我不想 Join() 因为它会锁定 UI(这是我使用线程的全部原因!)。

最佳实践是在我的线程方法结束时触发某种事件,并让该事件完成我需要的已完成的事情吗?

投票比较好

   while(!_threadFinishedStarting)
   {
        Application.DoEvents();
        Thread.Sleep(100);
   }

这里提到:C#.net - How to alert program that the thread is finished (event driven)?

非常感谢

【问题讨论】:

    标签: c# multithreading com vsto sta


    【解决方案1】:

    您可以在启动线程之前调用 Thread.SetApartmentState() 来选择一个 STA。您还必须抽取消息循环,这是 STA 线程的要求。这往往很困难并且经常被跳过,如果您的代码死锁或您的 IMessageFilter 抱怨,您知道您需要一个。

    注意另一个要求,STA 只有在您还创建要在同一线程上使用的对象时才有效。这往往是 VSTO 加载项中的问题,您通常希望使用 Office 对象模型提供的对象。您无法选择创建该对象的位置。

    如果这完全正确,那么您不会提前创建自己的 STA 线程,因为无论如何调用都会被编组。在这种情况下,BGW 就可以了,因为无论如何您都无法取得进展,因此在这两种情况下,呼叫都会被编组。线程安全没有免费的午餐。

    【讨论】:

    • 非常感谢汉斯。关于传递对象,我正在用 VSTOContrib 包装我的所有 COM 调用(因为 Office 的 COM 非常有问题,以至于它似乎需要第 3 方处理)。因此,理论上我的所有对象都是在线程中创建的(我不确定这是否完全适用于 COM 代理对象)。严格控制的 STA 线程似乎已经部分解决了我的问题(BGW 无法工作,因为它都是 OLE/COM 讨厌的 MTA)。
    • Office 程序员在认为“第 3 方处置”很重要时,永远都在给自己挖一个无法摆脱的巨大漏洞。背景资料is here。如果微软可以完全覆盖互操作,那就太好了,但这并没有真正起作用。您确实必须更多地了解机器内部的齿轮是如何工作的。知道有齿轮与知道它们有多少齿并不完全相同。
    • @HansPassant 你是说GC.Collect() 是唯一需要在 VSTO 解决方案中删除对 COM 对象的引用吗?没人需要Marshal.ReleaseComObject()
    猜你喜欢
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多