views:

44

answers:

2

Following up from part of this question, what is the best way to have a worker thread that invokes a COM procedure in a DLL, to do this asynchronously so that the worker thread is not blocked on this call?

Note that a call to this COM DLL can take a long time as it will do DB accesses and possible run long running queries.

I wondered if asynch is possible in this scenario or if one has to just wait for the call to complete?

+3  A: 

Take a look at this article:

http://msdn.microsoft.com/en-us/magazine/cc301334.aspx

You can also do it by yourself: create another thread for COM calls, and pass information from your worker thread to it somehow - for instance, using a queue of command pattern objects.

http://en.wikipedia.org/wiki/Command_pattern

Fabio Ceconello
+1  A: 

This is, in general, not possible. COM takes care of the threading requirements for a COM server. Which it advertises in the registry. Have a look-see with Regedit.exe and locate the HKCR\CLSID{guid} key for the coclass that you use. The ThreadingModel key says what is required.

If it is missing or set to Apartment then the server says that it needs to be created on an STA thread and its interface methods must be called from that same thread. If you call a method from another thread then the call gets marshaled to the STA thread. That's safe but it is slow and you don't have any concurrency.

If it is set to Both then the call is still marshaled when the COM object was created on an STA thread. But not when it was created on an MTA thread. Only Free allows free threading. Which is very rare, the vast majority of COM components are apartment threaded and don't have the internal protection that's required to make calls from a worker thread.

There's typically only one STA thread in a program, the startup thread. It must pump a message loop, a hard requirement for STA. If you don't have one, COM will create an STA thread for you to find a good home for the server. All calls will be marshaled then.

Not good news, I'm sure, there's no free lunch in threading.

Hans Passant
So do you mean I cannot make a COM call from a worker thread or that I cannot make a COM call asynch?
Tony
You *can* make a COM call from a worker thread. It just won't execute on that thread. It won't be async, your thread will be blocked for a while until the call completes.
Hans Passant