在 C# 中检测 COM RCW 对象的跨线程封送处理

发布于 2024-12-02 03:11:37 字数 853 浏览 1 评论 0原文

我正在处理大量 COM 互操作的大型多线程 C# 应用程序。我和其他开发人员有足够的机会意外调用 单线程单元 (STA) 来自 MTA 线程和未在其上创建它们的 STA 线程的 COM 对象。性能缓慢,跨线程编组是主要嫌疑点。

有没有好的方法来测试跨单元编组?更好的是,是否有一种防御性编程技术来测试给定的 COM 对象是否属于该线程的单元?

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

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

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

一个在线消息来源表明这是不可能的( http://www.pcreview.co.uk/forums/detecting-cross-apartment-com-calls-t2450589.html),CLR 掩盖了太多COM 代理对象的权限,使它们可以在高层访问。

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

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

合约呢 2024-12-09 03:11:37

您应该能够通过测试是否可以访问 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文