2017-06-27 66 views
1

在線程完成任何工作之前,每個線程初始化COM一次COM編碼是否正確,然後根據需要使用盡可能多的COM調用?爲多個COM操作初始化COM

舉例來說,在我的工作線程我成立卷影複製服務,還可以使用IFileOperation,在我的GUI線程使用我的CoCreateInstance(CLSID_ShellLink...)桌面上創建快捷方式,並使用CoCreateInstance(CLSID_TaskScheduler...)創建任務計劃程序作業。然後,對於所有這些操作,我只需在啓動程序和線程時每個線程調用HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);一次。最後還有CoUninitialize。

+1

它不是。你做出承諾*,交叉你的心,希望死亡。提供COM運行時自身無法弄清楚的細節。你保證你會抽出一個消息循環並且不會阻塞線程。你違背了兩個承諾。也許你會擺脫它,取決於。你知道你沒有當你的程序死鎖或事件沒有得到提升。你永遠無法100%確定它是安全的,你不知道其他代碼在另一臺依賴於你遵守諾言的機器上注入了什麼。不可能調試,不僅僅是因爲你不會接近機器。 –

+0

你可以使用更簡單的條款嗎?我有點迷路..作爲一個COM初學者......你是指在消息循環方面使用COINIT_APARTMENTTHREADED?什麼是做事的最佳方式? –

+0

是的。獲取消息循環並非難事,你總是從WPF或Winforms項目模板中獲得一個。如果你不想要,你不必創建一個窗口。 –

回答

2

CoInitialize(Ex)需要的基本知識被要求使用COM每個線程。

如果這些是「您的」線程 - 即您控制了它們的生命週期,則通常在線程函數的開始和結束處使用CoInitialize/Uninitialize。

這不是你的線程

這是一個有點棘手,如果線程是由其他人創建的,而你不知道COM是否已初始化與否(例如,當您的DLL加載插件和通過一個「正常」的導出函數調用)

有兩種方法可以去這裏:

(一)嘗試CoInitialize的(防爆),並標出返回代碼。

  • S_OK意味着你初始化COM庫,你需要調用CoUninitialize
  • S_FALSE意味着COM庫已被初始化與兼容的線程模型,但你仍然需要CoUninitialize調用(以「反」)的CoInitalue
  • 錯誤代碼(FAILED(hr) == true),這通常意味着COM庫已經初始化,但是線程模型與您請求的線程模型不兼容。難道調用CoUninitialize如果返回錯誤

(二)創建您自己的線程
......並且把你所有的COM工作存在(這可能無法與所有插件API的)

OleInitialize與CoInitializeEx的

一些Windows的API可能需要OleInitialize這是 「CoInitialize的還有更多。」

沒有很好的記錄哪些服務需要OleInitialize,但是我遇到了一些Shell API的問題。 (即使主線程確實OleInitialize,工作線程仍然使用CoInitializeEx

+0

謝謝peterchen。當你在線程函數的開始和結尾說 - 我使用Qt,所以我有一個工作對象生活在一個工作線程中,我可以傳遞執行需要在工作線程中執行的代碼的事件 - 在我的大小寫的情況下,當工作線程和工作對象被創建並且在刪除時未初始化時,我是否需要初始化?或者,我只是在使用COM的worker對象函數的開頭和結尾處初始化/取消初始化?那麼每個線程在生命週期的開始和結束時或者線程執行的每個函數執行一次? –

+0

通常,每個線程一次,因爲init/deinit有一些開銷,並且讓COM對象「生存」,Uninitialize/Initialize可能是未定義的行爲。我對QT線程不夠熟悉 - 可能最好爲此打開一個單獨的問題。 – peterchen

+0

我相信在調用CoInitialize之前就已經足夠了,而不必調用OleInitialize,但它似乎已經發生了變化,所以也需要明確地調用它。你注意到了嗎? –