简体   繁体   中英

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

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.

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. 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.

So, is it safe to make calls to the IAudioEndpointVolume interface from different threads with the code above? 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 .

CoInitialize(NULL) initializes single threaded apartment (STA) and interface pointers you have there are only [supposed to be] valid on this thread only. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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