views:

84

answers:

3

i have a COM object that i am using in dotnet and i have to call it always on the same thread. The issue is that conceptually it is being for multiple things throughout the program. What is the best way for ensuring that all uses of this object on called on this one specific background thread? Example code would be great.

+2  A: 

You could start a thread at program startup, which should handle all the COM interaction. Then you could have a wrapper object which pushes tasks onto a queue for the thread to handle.

The wrapper could contain synchronization code in order to hide the multi-threadedness to callers (ie. expose the wrapped calls as synchronous methods).

If this is a WinForms project, perhaps you could cut corners by simply using the GUI thread and the Control.Invoke method. (But if the calls take a long time, it is not a good idea, since you would be blocking the UI during the call).

driis
A: 

If you can the object under STA then it is granted to be called on the same thread.
For that you need to add STAThreadAttribute on your Main.
The only problem is that ALL COM objects will be handled that way.

Shay Erlichmen
A: 

In order to do this, you must first establish a way to get a particular call onto a particular thread. .Net has several built-in mechanisms for doing this but I find the easiest is the SynchronizationContext class. Both WinForms and WPF establish a SynchronizationContext instance for any thread where they are running a message loop.

So I would ...

  • Start a new thread for the object
  • Create a hidden WinForms or WPF window and run it
  • Grab the SynchronizationContext for that thread
  • Create the COM object on that thread

Now you have a location for the COM object and the means to get a call back onto the correct thread. The next step would be to create a proxy object. This object should have all of the methods for the COM object (and potentially just implement the COM interface). It would then take every method call and proxy the call off to the real COM object using the synchronization context.

public class Foo {
  private ComFoo _com;
  private SynchronizationContext _context;
  public void Bar() { 
    _context.Send(notUsed => _com.Bar(););
  }
}
JaredPar
@JaredPar, that's the start of a very good answer, but I, personally, would need more to get it working quickly. Maybe others would, as well. Can you show what the hidden window is about? How to assoc. the thread with it?
John Saunders