简体   繁体   English

从BackgroundWorker C#调用的CoInitialize

[英]CoInitialize Called from BackgroundWorker C#

I have a C# Windows Form application that utilizes a C++ DLL. 我有一个利用C ++ DLL的C#Windows窗体应用程序。 Within the DLL, I initialize COM: 在DLL中,我初始化COM:

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

When I run the DLL outside of a BackgroundWorker process, everything works fine. 当我在BackgroundWorker进程之外运行DLL时,一切正常。 If I do though, my application freezes when the DLL is finished. 如果我这样做,则DLL完成后我的应用程序将冻结。 So, I'm attempting to use a BackgroundWorker; 因此,我正在尝试使用BackgroundWorker。 but whenever I run the DLL within the DoWork function I am unable to initialize COM. 但是每当我在DoWork函数中运行DLL时,都无法初始化COM。

Could someone explain this, please, and offer any suggestions on how to run my DLL in the BackgroundWorker? 有人可以解释一下,并提供有关如何在BackgroundWorker中运行我的DLL的任何建议吗?

Thank you. 谢谢。

BackgroundWorker uses thread pool threads. BackgroundWorker使用线程池线程。 .NET thread pool threads are automatically initialized to MTA ( CoInitializeEx(NULL, COINIT_MULTITHREADED) ). .NET线程池线程会自动初始化为MTA( CoInitializeEx(NULL, COINIT_MULTITHREADED) )。 Your DLL is trying to initialize the thread to STA ( CoInitialize() ), and that call should be returning RPC_E_CHANGED_MODE . 您的DLL试图将线程初始化为STA( CoInitialize() ),并且该调用应返回RPC_E_CHANGED_MODE This is a failure. 这是失败的。

Typically, I wouldn't initialize COM on the calling thread from within a library. 通常,我不会从库中在调用线程上初始化COM。 I would consider this an antipattern. 我认为这是一种反模式。 Multiple libraries can be used by a single client application, and each of those libraries might (try to) initialize COM. 单个客户端应用程序可以使用多个库,并且每个库都可以(尝试)初始化COM。 A better design is to have the owner of each thread initialize COM on that thread. 更好的设计是让每个线程的所有者在该线程上初始化COM。 Your client application would initialize COM for the main thread and any background threads it owns (.NET does all this for you). 您的客户端应用程序将为主线程及其拥有的任何后台线程初始化COM(.NET为您完成所有这些操作)。 Each library would specify (in documentation) the threading/apartment requirements for its entry points (eg "This DLL's FooExport function must be called from an STA thread."). 每个库都会(在文档中)为其入口点指定线程/ FooExport要求(例如,“必须从STA线程调用此DLL的FooExport函数。”)。 Threads owned by the library would have their apartment state controlled by the library. 图书馆拥有的线程的公寓状态将由图书馆控制。 The only real advantage to calling CoInitialize/Ex from within the library is to try to detect the apartment state that your thread is currently in so that the library's apartment requirements are checked programmatically, but there are some scenarios (neutral-threaded apartments) in which that becomes problematic. 从库中调用CoInitialize/Ex的唯一真正好处是,尝试检测线程当前所在的单元状态,以便以编程方式检查库的单元需求,但是在某些情况下(中性线程单元)这成为问题。

To your scenario: 对于您的方案:

  • If your DLL requires STA, create the background thread manually in your client application, and set the apartment state to STA before starting the thread (see SetApartmentState ). 如果您的DLL需要STA,请在客户端应用程序中手动创建后台线程,并在启动线程之前将单元状态设置为STA(请参阅SetApartmentState )。 Also consider removing the CoInitialize call in your library. 还可以考虑删除库中的CoInitialize调用。
  • If your DLL can use MTA, either remove the CoInitialize call from your DLL, or use CoInitializeEx(NULL, COINIT_MULTITHREADED) . 如果您的DLL可以使用MTA,请从您的DLL中删除CoInitialize调用,或者使用CoInitializeEx(NULL, COINIT_MULTITHREADED)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM