2014-09-06 74 views
4

的COINIT - 用於指定窗口線程是否是在單個或線程單元的枚舉 - 文檔(http://msdn.microsoft.com/en-gb/library/windows/desktop/ms678505(v=vs.85).aspx)指出:爲什麼gui線程不能在多線程的公寓中運行?

多線程單元是用於通過非GUI線程使用。多線程套件中的線程不應該執行UI操作。這是因爲UI線程需要消息泵,並且COM不會爲多線程單元中的線程抽取消息。

爲什麼不應該在多線程的線程的公寓執行UI操作?在多線程公寓的線程中發生消息循環有什麼問題? COM以某種方式爲單線程單元中的線程提供自動消息循環?

+1

您可以創建一個線程,擁有它加入MTA,然後在其上運行的消息泵;沒有什麼能阻止你但是,這通常是毫無意義的。如果你在COM服務器上這樣做,並且客戶端在你的COM對象上調用一個方法,這個調用將在*不同的* MTA線程上執行(一個來自COM運行時管理的池)。此外,如果您在這個線程的外的公寓COM調用,調用將阻塞你的UI會出現雄(而從STA線程的亂公寓COM調用旋轉模態的消息泵在等待呼叫返回)。 – 2014-09-06 17:19:45

+1

是的 - 當COM代表您創建STA線程時,此線程將運行消息泵。這發生在MTA線程創建進程內STA COM對象時。 – 2014-09-06 17:21:03

+0

「多線程單元中的線程中發生消息循環有什麼問題?」這不是問題。問題是(正如它在你引用的文檔中所說的)「COM不會爲多線程公寓中的線程抽取消息」。這意味着如果COM需要等待,它將會等待,而不會泵送消息,這會掛起你的UI。 COM在單線程單元中等待時會抽出消息。 – 2014-09-06 17:30:25

回答

5

這是一個有點落後,一個UI線程主要是需要一個消息循環,以便它可以從Windows和其他進程收到通知。消息循環是producer-consumer problem的通用解決方案。隨着操作系統和其他進程的產生,UI線程消耗。

一個UI線程使用很多很多的代碼不是線程安全的。這包括在COM中實現的主要功能,如拖放,剪貼板,外殼對話框,ActiveX控件(如瀏覽器)。而且大量的代碼從來沒有成爲線程安全的,因爲程序員不必這樣做,寫起來更容易。這些功能需要一個STA線程,換句話說就是通過將COINIT_APARTMENTTHREADED傳遞給CoInitializeEx()來初始化COM的線程。

這是一個承諾給COM,該線程將是一個好公民,它是不允許進行阻塞調用,並且必須泵送消息循環。它是COM用於將工作線程調用封送到STA線程以保持COM對象線程安全的消息循環。當所有的呼叫都是由同一個線程完成的,那麼就沒有安全問題。底層的調用是SendMessage(),用大量的管道將函數參數從一個堆棧複製到另一個堆棧。 CoInitializeEx()創建一個隱藏的消息窗口,該消息窗口由處理消息並實際進行呼叫的STA線程擁有。安全。

相關問題