簡體   English   中英

從BackgroundWorker C#調用的CoInitialize

[英]CoInitialize Called from BackgroundWorker C#

我有一個利用C ++ DLL的C#Windows窗體應用程序。 在DLL中,我初始化COM:

auto hResult = CoInitialize(NULL); // Initialize COM
if (hResult != S_OK && hResult != S_FALSE) { 
    WSACleanup(); 
    return 1; 
}

當我在BackgroundWorker進程之外運行DLL時,一切正常。 如果我這樣做,則DLL完成后我的應用程序將凍結。 因此,我正在嘗試使用BackgroundWorker。 但是每當我在DoWork函數中運行DLL時,都無法初始化COM。

有人可以解釋一下,並提供有關如何在BackgroundWorker中運行我的DLL的任何建議嗎?

謝謝。

BackgroundWorker使用線程池線程。 .NET線程池線程會自動初始化為MTA( CoInitializeEx(NULL, COINIT_MULTITHREADED) )。 您的DLL試圖將線程初始化為STA( CoInitialize() ),並且該調用應返回RPC_E_CHANGED_MODE 這是失敗的。

通常,我不會從庫中在調用線程上初始化COM。 我認為這是一種反模式。 單個客戶端應用程序可以使用多個庫,並且每個庫都可以(嘗試)初始化COM。 更好的設計是讓每個線程的所有者在該線程上初始化COM。 您的客戶端應用程序將為主線程及其擁有的任何后台線程初始化COM(.NET為您完成所有這些操作)。 每個庫都會(在文檔中)為其入口點指定線程/ FooExport要求(例如,“必須從STA線程調用此DLL的FooExport函數。”)。 圖書館擁有的線程的公寓狀態將由圖書館控制。 從庫中調用CoInitialize/Ex的唯一真正好處是,嘗試檢測線程當前所在的單元狀態,以便以編程方式檢查庫的單元需求,但是在某些情況下(中性線程單元)這成為問題。

對於您的方案:

  • 如果您的DLL需要STA,請在客戶端應用程序中手動創建后台線程,並在啟動線程之前將單元狀態設置為STA(請參閱SetApartmentState )。 還可以考慮刪除庫中的CoInitialize調用。
  • 如果您的DLL可以使用MTA,請從您的DLL中刪除CoInitialize調用,或者使用CoInitializeEx(NULL, COINIT_MULTITHREADED)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM