简体   繁体   English

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

[英]Can I access the interface of a COM object from different threads?

I get access to the IAudioEndpointVolume interface in the main worker thread of a service like this (error checks omitted): 我可以访问像这样的服务的主工作线程中的IAudioEndpointVolume接口(省略错误检查):

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);

The CAudioEndpointVolumeCallback class then stores the IAudioEndpointVolume pointer in a member variable and calls RegisterControlChangeNotify(this) on it in its constructor. 然后, CAudioEndpointVolumeCallback类将IAudioEndpointVolume指针存储在成员变量中,并在其构造函数中对其调用RegisterControlChangeNotify(this)

This class may also start a thread to smoothly change the volume from one value to another over a short time period. 此类还可以启动一个线程,以便在短时间内将音量从一个值平滑地更改为另一个值。 So at the end I make calls to the IAudioEndpointVolume interface from different threads. 所以最后我从不同的线程调用IAudioEndpointVolume接口。 In general all of this works as intended, but I am experiencing some strange behavior in some edge cases. 一般来说,所有这些都按预期工作,但我在某些边缘情况下遇到了一些奇怪的行为。 When checking the code again I stumbled across the comments about threading in the MSDN documentation (I don't have any prior experience with COM objects) and wondered if what I am doing is correct. 当我再次检查代码时,我偶然发现了MSDN文档中有关线程的注释(我没有任何关于COM对象的经验),并想知道我所做的是否正确。

So, is it safe to make calls to the IAudioEndpointVolume interface from different threads with the code above? 那么,使用上面的代码从不同的线程调用IAudioEndpointVolume接口是否安全? Do I have to protect those calls with a mutex? 我是否必须使用互斥锁来保护这些呼叫?

I am a bit confused and am not sure if I really understood the behavior of the COM Threading Models . 我有点困惑,我不确定我是否真的理解COM线程模型行为

CoInitialize(NULL) initializes single threaded apartment (STA) and interface pointers you have there are only [supposed to be] valid on this thread only. CoInitialize(NULL)初始化单线程单元(STA)和接口指针,只有[应该]在此线程上有效。 You can pass them to another thread through GIT , or by CoMarshalInterThreadInterfaceInStream on this thread and getting a "duplicate" of it back with CoGetInterfaceAndReleaseStream on the target thread, where you are going to use it. 您可以通过GIT或者通过此线程上的CoMarshalInterThreadInterfaceInStream将它们传递给另一个线程,并通过目标线程上的CoGetInterfaceAndReleaseStream获取它的“重复”,您将在其中使用它。

Depending on implementation behind the interface pointer in question you might eventually obtain the same pointer (in which case the whole trick would be equal to simply using the pointer on another thread), however this is not safe in general case. 根据所讨论的接口指针背后的实现,您最终可能获得相同的指针(在这种情况下,整个技巧将等于简单地使用另一个线程上的指针),但是在一般情况下这不安全。

Another option is to use MTA (as opposed to STA) and then you are allowed to pass pointers directly among all/any MTA threads. 另一种选择是使用MTA(而不是STA),然后允许您在所有/任何MTA线程之间直接传递指针。

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

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