2013-07-28 46 views
1

我正在构建一个VSTO加载项:我需要运行后台线程,但此线程需要访问COM组件(我实现了IMessageFilter以使此消息尽可能安全)。所有访问OLE或COM的线程必须是STA,我相信;因此,BackgroundWorker不在桌面上。VSTO后台线程与STA和COM

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

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

OR

是更好地轮询

​​

如此地:C#.net - How to alert program that the thread is finished (event driven)?

非常感谢

回答

1

你可以叫Thread.SetApartmentState()之前选择一个STA你开始线程。您还必须抽取消息循环,这是STA线程的一项要求。这往往是困难的,经常跳过,你知道你需要一个,如果你的代码死锁或IMessageFilter抱怨。

要小心另一个要求,当你也是创建你想在同一个线程上使用的对象时,一个STA只有效。这往往是VSTO加载项中的问题,您通常需要使用Office对象模型提供的对象。您无法选择该对象的创建位置。

如果这是完全正确的,那么你就是而不是之前创建自己的STA线程,因为无论如何都会调用呼叫。在这种情况下,BGW就好了,因为无论如何你都无法前进,在这两种情况下,呼叫都会被封送。没有免费的线程安全午餐。

+0

非常感谢汉斯。关于传递对象,我用VSTOContrib封装了所有的COM调用(因为Office的COM很麻烦,似乎需要第三方处理)。因此,我的所有对象在理论上都是在线程中创建的(我不确定这是否完全适用于COM代理对象)。 严重控制的STA线程似乎已经部分解决了我的问题(BGW无法工作,因为它是OLE/COM讨厌的所有MTA)。 – user1713993

+1

办公室程序员永远挖掘自己一个巨大的漏洞,当他们认为“第三方处置”很重要时,他们无法摆脱困境。 Backgrounder [在这里](http://stackoverflow.com/questions/17130382/understanding-garbage-collection-in-net/17131389#17131389)。如果微软能够完全通过互联网进行交易,那将是一件好事,但这并不是真的有效。您必须了解更多有关机器内部齿轮如何工作的信息。知道有齿轮与知道它们有多少齿不完全相同。 –

+0

@HansPassant你是否说过''GC.Collect()'是移除VSTO解决方案中COM对象引用所需的唯一东西?没有人需要'Marshal.ReleaseComObject()'? – Chris