Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are STA COM components handled when used in a WCF service hosted in IIS (7+)?

Tags:

iis

wcf

com

sta

From what I understand, when a COM component marked as using STA is used from an MTA thread, the calls are supposed to be marshalled to an STA thread and executed from that dedicated thread. In the case of a Windows client application, this would mean that it would execute on the UI thread (if marked as STA), and that callbacks from the COM component to me would be handled by Windows messages sent to a hidden window and processed on the Windows message loop.

What happens though if I use a STA COM component in a WCF service hosted in IIS? Will the worker process have a Windows message loop on a STA thread? Can I fire up my own STA thread with its own message loop?

like image 550
SoftMemes Avatar asked Oct 07 '10 09:10

SoftMemes


1 Answers

The COM runtime looks after the dispatching of calls to methods on a COM object inside an STA: you are right that this is based on the same OS mechanism used for dispatching Windows messages, but you don't need to worry about making this happen - COM does this for you under the hood.

What you do need to worry about is which STA your COM objects are going to live in. If you instantiate apartment-threaded COM objects using COM Interop from a WCF service, you need to be careful.

If the thread on which you do this is not an STA thread, then all in-process COM objects will live in the default Host STA for the IIS worker process. You do not want this to happen: all your COM objects for all service operations will end up in this same STA. The clue is in the name - there is just one thread for all the objects - and all calls to their methods will be serialized waiting for the one and only thread in the apartment to execute them. Your service will not scale to handle multiple concurrent clients.

You need to make sure that COM objects you instantiate to service a particular WCF request are in their own STA separate from objects created for other requests. There are broadly two ways to do this:

  • Spin up your own Thread, specifying ApartmentState.STA in SetApartmentState() before you start it, on which to instantiate the COM objects for a particular request. This is the approach detailed by Scott Seely in the link in Kev's answer: he ensures that each service operation call is invoked on a new STA-initialised Thread. A harder but more scalable solution along these lines would be to implement a pool of reusable STA-initialised Threads.
  • Host your COM objects in a COM+ Application, so that they live in a separate DllHost process, where COM+ (through its abstraction called the Activity) can take care of putting the objects for different requests into different STAs.

I'm not sure exactly what you mean when you refer to callbacks. Perhaps you mean COM method calls on some COM interface implemented in your managed code, via a reference passed in to the COM objects as an argument to one of the COM objects' methods: if so, this should just work. But perhaps you mean something else, in which case perhaps you could amend the question to clarify.

like image 108
Chris Dickson Avatar answered Nov 15 '22 07:11

Chris Dickson