c# - 在 WinForms 线程上使用 CoInitializeEx

标签 c# .net multithreading com apartments

我正在为 DSLR 相机开发一个 SDK,其中包含以下说明:

Notes on Developing Windows Applications When creating applications that run under Windows, a COM initialization is required for each thread in order to access a camera from a thread other than the main thread. To create a user thread and access the camera from that thread, be sure to execute CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ) at the start of the thread and CoUnInitialize() at the end. Sample code is shown below. This is the same when controlling EdsVolumeRef or EdsDirectoryItemRef objects from another thread, not just with EdsCameraRef.

void TakePicture(EdsCameraRef camera)
{
    // Executed by another thread
    HANDLE hThread = (HANDLE)_beginthread(threadProc, 0, camera);
    // Block until finished
    ::WaitForSingleObject( hThread, INFINITE );
}

void threadProc(void* lParam)
{
    EdsCameraRef camera = (EdsCameraRef)lParam;
    CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
    EdsSendCommand(camera, kEdsCameraCommand_TakePicture, 0);
    CoUninitialize();
    _endthread();
}

我的应用程序是一个 C# WinForms 应用程序,通常我使用托管线程类和 Control.Invoke 函数来避免跨线程问题。

由于我没有用于使用 SDK 的 C# 示例源代码,我的问题是,在标有 [STAThread 的应用程序中使用 CoInitializeEx 是否有用和/或有必要] 属性?

我还没有遇到过需要让我的应用程序为线程创建一个新单元的场景,因此一些见解将有助于更好地理解线程模型。

更新:在阅读了更多关于公寓和 COM 的内容后,它开始变得有些道理了。现在我想知道 .NET 托管线程类的默认值是什么,我们可以在没有 P/Invoke 的情况下以托管方式为每个线程指定一个单元模型吗?

最佳答案

a COM initialization is required for each thread

是的,坚如磐石的要求。如此之多,以至于 CLR 会自动执行此操作,而无需您提供帮助。每个 .NET 线程在开始运行之前都会调用 CoInitializeEx()。

CLR 需要知道传递给 CoInitializeEx() 的参数,在 STA 和 MTA 之间进行选择。对于 Winforms 程序的启动线程,它由 Program.cs 中 Main() 方法的 [STAThread] 属性确定。 必须是 STA,这是显示 UI 的线程的硬性要求。对于您自己启动的任何线程,它由您对 Thread.SetApartmentState() 的调用决定,默认为 MTA。对于任何线程池线程,如 BackgroundWorker 或 Task 或 QUWI 使用的线程,它始终是 MTA 且无法更改。如果正确使用,此类线程的自动结果永远无法正确支持 STA。

这也是您的代码片段做错的地方,启动 STA 线程而不抽取消息循环是非法的。你往往会意外地逃脱它。有时你不这样做,代码会死锁或以其他方式失败,比如没有引发预期的事件。由于供应商批准它做错了,所以在这里可能无关紧要。但是,如果您曾经注意到死锁,那么您就会知道去哪里查找。

长话短说,你不能自己调用​​ CoInitializeEx(),它已经完成了。

关于c# - 在 WinForms 线程上使用 CoInitializeEx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29385515/

相关文章:

.NET IoC : Configure library components from (application) composition root

c# - 使用 Selenium webdriver + Specflow + C#+ 页面对象模式验证订单摘要页面中添加到购物车的多个产品的功能是否相同

c# - MessageBox 关闭后结束程序

c# - WPF MVVM 导航技术

c# - last_insert_id 多线程

java - Repaint() 只工作了一半

c++ - 在 C++ 中,原始类型静态初始化为常量值是线程安全的吗?

c# - Xamarin.Android : Add the dynamic menu items to Navigation view of DrawerLayout

.net - 使用 MVVM 轻量级工具包动态创建 ViewModel

c# - C#中的无锁优先级队列