Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以从不同的线程访问COM对象的接口吗?_C++_Multithreading_Winapi_Com - Fatal编程技术网

C++ 我可以从不同的线程访问COM对象的接口吗?

C++ 我可以从不同的线程访问COM对象的接口吗?,c++,multithreading,winapi,com,C++,Multithreading,Winapi,Com,我在服务的主工作线程中访问接口,如下所示(省略错误检查): 然后,CAudioEndpointVolumeCallback类将IAudioEndpointVolume指针存储在成员变量中,并在其构造函数中对其调用RegisterControlChangeNotify(this) 此类还可以启动线程,以便在短时间内将音量从一个值平滑地更改为另一个值。因此,在最后,我从不同的线程调用IAudioEndpointVolume接口。总的来说,所有这些都能按预期工作,但在某些边缘情况下,我遇到了一些奇怪的

我在服务的主工作线程中访问接口,如下所示(省略错误检查):

然后,
CAudioEndpointVolumeCallback
类将
IAudioEndpointVolume
指针存储在成员变量中,并在其构造函数中对其调用
RegisterControlChangeNotify(this)

此类还可以启动线程,以便在短时间内将音量从一个值平滑地更改为另一个值。因此,在最后,我从不同的线程调用
IAudioEndpointVolume
接口。总的来说,所有这些都能按预期工作,但在某些边缘情况下,我遇到了一些奇怪的行为。当再次检查代码时,我偶然发现了MSDN文档中关于线程的注释(我以前没有任何COM对象的经验),并想知道我所做的是否正确

那么,使用上述代码从不同线程调用
IAudioEndpointVolume
接口安全吗?我必须用互斥锁保护这些呼叫吗

我有点困惑,不确定我是否真的理解了。

CoInitialize(NULL)
初始化单线程单元(STA),并且您那里的接口指针仅[应该]在此线程上有效。您可以通过将它们传递给另一个线程,或者通过在这个线程上获取它的“副本”,并在目标线程上使用它

取决于所讨论的接口指针后面的实现,您可能最终获得相同的指针(在这种情况下,整个技巧将等同于在另一个线程上简单地使用指针),但是在一般情况下这是不安全的


另一种选择是使用MTA(与STA相反),然后允许您在所有/任何MTA线程之间直接传递指针。

因此,如果我使用
CoInitializeEx(NULL,Conit\u MULTITHREADED)
并使用互斥锁保护对接口的访问,我是否安全?但是我必须在两个/所有线程中调用
CoInitializeEx
?是的,您是安全的。是的,在所有线程上。但是请注意,您通常没有选择STA/MTA的灵活性。如果调用方已经将线程初始化为STA,则您没有重新初始化的选项。在大多数情况下,问题是这样表述的:“我的代码在STA(MTA)线程上运行,如何在工作线程上正确使用指针”。考虑到您从获取接口指针的同一线程进行调用,这很可能与线程无关。这很可能与使用服务有很大关系。你应该引用你的。我并不是从获取指针的同一线程调用(所有)的!我对我的代码做了一些关于线程安全的修改,这解决了我在这项服务中遇到的一些其他问题。因此,这为我指明了方向,让我发布了这个问题。稍后我将从另一个问题中尝试你的建议。事实上,我怀疑它是否能解决上面评论中提到的问题。不管怎样我都要试试。但是,请不要将此视为个人隐私;)
CoInitialize(NULL);
CoCreateGuid(&g_guidMyContext);
CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, (void**)&m_pEnumerator);

IMMDevice *pEndpoint = NULL;
m_pEnumerator->GetDevice(&deviceID[0], &pEndpoint);

IAudioEndpointVolume *pAudioVol = NULL;
pEndpoint->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioVol);

CAudioEndpointVolumeCallback *pVolumeCallback = new CAudioEndpointVolumeCallback(pAudioVol, 100, TRUE, m_debugLog, m_logMutex);