c++ - 我可以从不同的线程访问 COM 对象的接口(interface)吗?

标签 c++ multithreading winapi com

我可以访问 IAudioEndpointVolume像这样的服务的主工作线程中的接口(interface)(省略了错误检查):

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来自不同线程的接口(interface)。总的来说,所有这些都按预期工作,但在某些边缘情况下我遇到了一些奇怪的行为。再次检查代码时,我偶然发现了 MSDN 文档中关于线程的评论(我之前没有任何使用 COM 对象的经验),我想知道我所做的是否正确。

那么,调用 IAudioEndpointVolume 是否安全?来自不同线程的接口(interface)与上面的代码?我是否必须使用互斥体来保护这些调用?

我有点困惑,不确定我是否真的理解 behavior of the COM Threading Models .

最佳答案

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

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

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

关于c++ - 我可以从不同的线程访问 COM 对象的接口(interface)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22203832/

相关文章:

c++ - OpenCv 将 vector 转换为矩阵 C++

java - 使用 Java 的非阻塞多线程 MySQL

java - 如果线程B希望看到线程A所做的更改,那么最后更改只能是volatile变量而不是全部变量吗?

c++ - 来自 QBitmap 的 QPixmap

c++ - 关于C++类的几个问题

c++ - 运算符中的 friend == 或 << 我应该什么时候使用它?

c++ - 为了清晰起见,是否应该经常跳过捷径、简洁和聪明?

multithreading - 如何检测和快速完成响应时间太长的lua功能?

ssl - 如何在 WinHttp 中设置客户端证书链

c++ - 使用 C++ 获取目录根目录