通过c#中的COM RCW对象检测跨线程封送

本文关键字:线程 检测 对象 中的 COM RCW 通过 | 更新日期: 2023-09-27 18:07:18

我在一个大型多线程c#应用程序中工作,处理大量的COM互操作。其他开发人员和我有足够的机会从MTA线程中偶然调用单线程公寓(STA) COM对象,而这些对象不是在STA线程中创建的。性能缓慢,跨线程封送是主要问题。

是否有一个好的方法来测试跨公寓封送?更好的是,是否存在一种防御性编程技术来测试给定的COM对象是否属于这个线程的单元?

我最接近的是在可疑代码周围放置一个防御的断言语句:

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

如果我们的BackgroundWorker线程正在调用STA对象,这将警告我们,我特别担心STA线程正在使用在另一个STA线程中创建的COM运行时可调用包装器(RCW)对象。

一个在线消息来源建议这是不可能的(http://www.pcreview.co.uk/forums/detecting-cross-apartment-com-calls-t2450589.html), CLR模糊了太多的COM代理对象,使它们在高层次上可访问。

我不敢相信这是唯一的答案。谢谢!

通过c#中的COM RCW对象检测跨线程封送

您应该能够通过测试是否可以访问immarshal接口来实现这一点,如果调用是跨单元调用,则应该将immarshal接口聚合到代理中。首先,你需要在项目的某个地方声明immarshal:

  [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