繁体   English   中英

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

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

我可以访问像这样的服务的主工作线程中的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);

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

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

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

我有点困惑,我不确定我是否真的理解COM线程模型行为

CoInitialize(NULL)初始化单线程单元(STA)和接口指针,只有[应该]在此线程上有效。 您可以通过GIT或者通过此线程上的CoMarshalInterThreadInterfaceInStream将它们传递给另一个线程,并通过目标线程上的CoGetInterfaceAndReleaseStream获取它的“重复”,您将在其中使用它。

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

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

暂无
暂无

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

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