2013-07-28 97 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