Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Moving interfaces between COM apartments

Status
Not open for further replies.

teriviret

Programmer
Dec 12, 2003
288
US
Okay, "COM apartments" are really kicking my butt today.

I wrote an MFC program which creates a COM object from a local server (EXE), creates a DirectShow filter from an in-process server, and then passes the COM object interface to the filter.

The problem is, the MFC program, COM object, and DirectShow filter are all in different COM apartments:

MFC program -- process A, single threaded apartment
COM object -- process B, multi threaded apartment
DirectShow filter -- process A, multi threaded apartment

When the DirectShow filter proceeds to call methods of the interface, sometimes they work, sometimes they don't. When they don't, either process A freezes, or I get exceptions thrown which mention "interface used was marshalled for a different apartment" or something like that.

I know that when an object in one apartment creates an object in another apartment and gets an interface to it, COM creates special proxy/stub modules to marshal the interface. So how can I take this interface and use it with a third apartment? Is there a way to "remarshal" the interface to work with another apartment?
 
I figured this out. Actually my DirectShow filter object itself was being created in process A's STA, but it was in a worker thread I spawned from it that I was using the interface that caused the errors. That worker thread was joining the MTA.

The solution I found was to use this pair of COM functions:

CoMarshalInterThreadInterfaceInStream
CoGetInterfaceAndReleaseStream

From process A's STA, I marshaled the interface into an IStream. Then I passed this IStream to process A's MTA. From there I unmarshaled the interface. So now process A's MTA can call an object in process B even though the original interface was created by process A's STA. It seems to work just as the documentation for these two functions says, although I'm concerned that there might be some inefficiency with two pairs of proxies/stubs and having to go through the application's message loop.

I also learned another interesting lesson. It seems that an MFC application, all calls to COM objects in the STA go through the program's message loop (makes sense, since there's only on thread, I guess). Another thing I was doing in the program was waiting inside a message handler for a DirectShow filter graph to change state. Well, one of the filters in the graph was calling back to an object in the STA, and the filter graph manager was waiting on this call to complete. It caused a strange deadlock that was only broken if I right-clicked on the application's task bar icon, which I guess forces the application's message loop to run and so gets the COM method call to complete.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top