在 C# 中检测 COM RCW 对象的跨线程封送处理
我正在处理大量 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您应该能够通过测试是否可以访问 IMarshal 接口来完成此操作,如果调用是跨公寓调用,则该接口应该聚合到代理中。首先,您需要在项目中的某个位置声明 IMarshal:
然后,您可以像这样测试接口。
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:
Then, you can test for the interface like so.