Do not pass the original interface pointer between the thread
One of the first batch of COM projects I have involved involving a distributed application containing 100,000 lines of code, which is written by a large software company in the US West Coast. The application creates dozens of COM objects on multiple machines and calls these objects from the background thread that started from the client process. The development team encountered a problem, calling either disappeared without a trace, or fail without obvious reasons. The most amazing symptoms they give me: When a call cannot return, launch other applications that support COM on the same machine (including Microsoft Paint, etc.) will cause these applications to be locked.
After checking their code, they violated a basic rule for Com concurrent, that is, if a thread is to share an interface pointer with another thread, it should first package the interface pointer. If necessary, the encapsulated interface pointer allows COM to create a new agent (and a new channel object, nodules the proxy and stubbing) to allow for adjustment from another unit. Do not pass the original interface pointer (one 32-bit address in memory) to another thread, will bypass the COM, and if the transmitted and received thread is in different units, there will be various adverse behavior. (In Windows 2000, since the two objects can share a unit, it is in different contexts, so if the thread is located in the same unit, you may be caught in a dilemma.) Typical symptoms include call failed and returned RPC_E_Wrong_thread_ERROR.
Windows NT 4.0 and later You can use a pair of API functions called ComarshalinteRFACEADERFACEINSTREAM and COGETINTERFACEANDRELEASTREAM, and easily block interface pointers between threads. Suppose one of your applications (thread a) created a COM object, which relates to an IFOO interface pointer, and another thread in the same process (thread b) wants to call this object. When preparing to pass the interface pointer to thread B, thread a should be sealed by the interface pointer, as shown below:
ComarshalinterthreadInterfaceInstream (IID_IFOO, PFOO, & PStream);
After ComarshalinterthreadInterfaceInstream returns, thread b can safely cancel the interface pointer:
IFoo * pfoo;
COGETINTERFACEANDRELEASTREAM (Pstream, IID_IFOO, (Void **) & pfoo);
In these examples, the PFOO is an IFO interface pointer, and PStream is an ISTREAM interface pointer. CoM initializes the IStream interface pointer when calling ComarshalinterthreadInterfaceInstream, then uses and releases the interface pointer inside COGETISTERFACEANDRELEASTREAM. In fact, you usually use an event or other synchronization primitive to coordinate the behavior of these two threads - for example, let thread b know that the interface pointer is ready, can be canceled.
Please note that the interface pointer does not have any problems in this way, because COM has sufficient intelligence, which is not to be sealed (or reinfert) pointers when it is not necessary to be sealed. If you do this, use COM, you can easily use COM.