Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting cross-thread marshaling by COM RCW objects in C#

I'm working in a large multithreaded C# application handling bunches of COM interop. The other developers and I have ample opportunity to accidentally call Single-Threaded Apartment (STA) COM objects from MTA threads, and from STA threads they weren't created on. Performance is sluggish, and cross-thread marshalling is a prime suspect.

Is there a good method to test for cross-apartment marshaling? Even better, is there a defensive programming technique to test that a given COM object belongs to this thread's apartment?

The closest I've come is an assert statement placed defensively around suspicious code:

Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA);
suspiciousComInterface.SomeMethod();

While this will warn us if our BackgroundWorker threads are calling STA objects, I am specifically worried that STA threads are using COM Runtime Callable Wrapper (RCW) objects that were created in another STA thread.

One online source suggested that this isn't possible (http://www.pcreview.co.uk/forums/detecting-cross-apartment-com-calls-t2450589.html), that the CLR obscures too much of the COM Proxy objects to make them accessible at a high-level.

I can't believe this is the only answer. Thanks!

like image 839
Scott B Avatar asked Aug 31 '11 03:08

Scott B


1 Answers

You should be able to accomplish this by testing whether you can get to the IMarshal interface, which should be aggregated into the proxy if the call is a cross-apartment call. First, you will need to declare IMarshal somewhere in your project:

  [System.Runtime.InteropServices.InterfaceTypeAttribute(1)]
  [System.Runtime.InteropServices.Guid("00000003-0000-0000-C000-000000000046")]
  public interface IMarshal
  {
     // no methods needed, just querying for the interface
  }

Then, you can test for the interface like so.

  if (suspiciousComInterface is IMarshal)
     // cross-apartment call
  else
     // direct call
like image 116
Brent M. Spell Avatar answered Sep 22 '22 21:09

Brent M. Spell