Thread Safety Problem
-
I have apartment threaded built VB activex control hosted on ATL dialog - they reside in thread T1. Another CComObject component in thread T2 of the same process - tries to access methods of this ActiveX control. There is an exception. I tried using Lock(), Unlock() provided by ATLModule, and also explicitly creating CComCriticalSection. But in vain. Can anyone help?
-
I have apartment threaded built VB activex control hosted on ATL dialog - they reside in thread T1. Another CComObject component in thread T2 of the same process - tries to access methods of this ActiveX control. There is an exception. I tried using Lock(), Unlock() provided by ATLModule, and also explicitly creating CComCriticalSection. But in vain. Can anyone help?
Someone wrote: Another CComObject component in thread T2 of the same process - tries to access methods of this ActiveX control. Please have a look at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmf_a2c_88tp.asp[^] Suppose you have the interface pointer
pCtrl
in thread T1. Then you cannot use that pointer straight away in thread T2. You would have to do something like this:IStream* pStream;
CoMarshalInterThreadInterfaceInStream(IID_ITheInterfaceID, pCtrl, &pStream);If the call is successful,
pStream
will be a stream containing a reference to your objectpCtrl
and apartment marshalling information. In thread T2, you pick up thepStream
object, and unmarshal the interface pointer from the stream like this:ITheInterface* pCtrl2;
// I can't remember if the stream needs to be rewound or not
// if this code fails, please see IStream::Seek()
CoGetInterfaceAndReleaseStream(pStream, IID_ITheInterfaceID, (void**)pCtrl2);The interface pointer
pCtrl2
will now be accessible in thread T2. Generally speaking, the interface pointer deserialized from a stream is accessible in the thread where it was deserialized. -- Arigato gozaimashita! -
Someone wrote: Another CComObject component in thread T2 of the same process - tries to access methods of this ActiveX control. Please have a look at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmf_a2c_88tp.asp[^] Suppose you have the interface pointer
pCtrl
in thread T1. Then you cannot use that pointer straight away in thread T2. You would have to do something like this:IStream* pStream;
CoMarshalInterThreadInterfaceInStream(IID_ITheInterfaceID, pCtrl, &pStream);If the call is successful,
pStream
will be a stream containing a reference to your objectpCtrl
and apartment marshalling information. In thread T2, you pick up thepStream
object, and unmarshal the interface pointer from the stream like this:ITheInterface* pCtrl2;
// I can't remember if the stream needs to be rewound or not
// if this code fails, please see IStream::Seek()
CoGetInterfaceAndReleaseStream(pStream, IID_ITheInterfaceID, (void**)pCtrl2);The interface pointer
pCtrl2
will now be accessible in thread T2. Generally speaking, the interface pointer deserialized from a stream is accessible in the thread where it was deserialized. -- Arigato gozaimashita!I tried this, but due to some runtime exception, changed to Global Interface Table. Now the problem is: I create instance of IGlobalInterfaceTable and marshal my interface into it using RegisterInterfaceInGlobal(..). It returns me HRESULT of Successful. Now if I Unmarshall this interface in the same thread somewhere down the line, I can successfully retriev it & call methods on this interface. Problem is that in another thread, when I create instance of Global interface table, and access the interface using global cookie, I get HRESULT of 0x8000FFFF which means catastrophic failure. The second thread calls CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); and CoUninitialize(). Also it waits for a event handle. Apart from the wait statement, the thread returns immediately. (it does not have message pump).