gpt4 book ai didi

c# - 从 BackgroundWorker C# 调用的 CoInitialize

转载 作者:行者123 更新时间:2023-11-28 04:50:38 25 4
gpt4 key购买 nike

我有一个使用 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 为您完成所有这些)。每个库都会(在文档中)指定其入口点的线程/单元要求(例如,“此 DLL 的 FooExport 函数必须从 STA 线程调用。”)。库拥有的线程的单元状态将由库控制。从库中调用 CoInitialize/Ex 的唯一真正好处是尝试检测您的线程当前所处的单元状态,以便以编程方式检查库的单元要求,但有一些场景(中性线程单元),这会成为问题。

针对您的场景:

  • 如果您的 DLL 需要 STA,请在您的客户端应用程序中手动创建后台线程,并在启动线程之前将单元状态设置为 STA(参见 SetApartmentState)。还可以考虑删除库中的 CoInitialize 调用。
  • 如果您的 DLL 可以使用 MTA,请从您的 DLL 中删除 CoInitialize 调用,或使用 CoInitializeEx(NULL, COINIT_MULTITHREADED)

关于c# - 从 BackgroundWorker C# 调用的 CoInitialize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48282022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com