Обнаружение межпоточного маршалинга объектами COM RCW в C # - PullRequest
11 голосов
/ 31 августа 2011

Я работаю в большом многопоточном приложении C #, обрабатывающем связки взаимодействия COM. У других разработчиков и у меня есть широкая возможность случайно вызвать Single-Threaded Apartment (STA) COM-объекты из потоков MTA и из потоков STA, на которых они не были созданы. Производительность вялая, и подозрительное распределение между потоками является главным подозрением.

Есть ли хороший метод для тестирования маршалинга между квартирами? Более того, существует ли метод защитного программирования для проверки того, что данный COM-объект принадлежит квартире этого потока?

Самое близкое, что я пришел, - это утверждение assert, защищающее подозрительный код:

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

Хотя это предупредит нас, если наши BackgroundWorker потоки вызывают объекты STA, я особенно обеспокоен тем, что потоки STA используют объекты COM Runtime Callable Wrapper (RCW), созданные в другом потоке STA.

Один онлайн-источник предположил, что это невозможно (http://www.pcreview.co.uk/forums/detecting-cross-apartment-com-calls-t2450589.html),, что CLR затеняет слишком много объектов COM-прокси, чтобы сделать их доступными на высоком уровне.

Не могу поверить, что это единственный ответ. Спасибо!

1 Ответ

12 голосов
/ 31 августа 2011

Вы сможете выполнить это, проверив, можете ли вы получить доступ к интерфейсу IMarshal, который должен быть агрегирован в прокси, если вызов является вызовом между квартирами. Во-первых, вам нужно объявить IMarshal где-нибудь в вашем проекте:

  [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
  }

Затем вы можете проверить интерфейс следующим образом.

  if (suspiciousComInterface is IMarshal)
     // cross-apartment call
  else
     // direct call
...