2012-05-18 66 views
2

我有一些COM对象,我正在.NET应用程序的线程上创建和运行。线程被标记为Single Threaded Apartments,并且一切似乎都在起作用。我的理解是,如果这些线程试图从主线程访问COM对象,那么这些对象将在.NET中自动被封送和序列化,所以即使在这种情况下,我也会处理这些事情,所有的事情都是安全和整洁的,尽管也许有点慢。在这种情况下是否需要STA消息循环?

我的问题是,虽然事情似乎工作正常,我是而不是在我创建的STA线程中抽取消息循环。如果可以的话,我宁愿避免消息循环,因为它会导致额外的复杂性(以及可能的效率损失)。

我读过一堆关于为什么消息循环是必要的建议(主要来自非常有帮助的Hans Passant),我的理解是消息循环在线程A上给出了一个位置,其中一些其他线程B可以请求居住在线程A上的COM对象可以被封送和播放。如果这是正确的,那么只要没有其他线程从线程A上的COM对象请求任何东西,线程A是否安全不抽取消息循环?或者还有其他情况下消息循环可能会发挥作用吗?

我在这里玩火吗?有没有一种情况下,你问你是否在玩火,而你不是?

+0

您有任何事件?你是否可以控制事件处理程序来确保它们的重新进入调用不会导致无限递归?如果您有消息泵,通常会使用发布消息来打破此循环。 –

+0

我想我不知道与此相关的问题。什么会导致一个事件发生在我创建并且没有其他人正在看的线程中?我正在使用的COM对象?据我所知,他们不会引发任何事件... – user12861

+0

如果您的COM对象的设计包括通知外部世界发生了什么,那么您可以实现传出事件接口,如IConnectionPointContainer。 –

回答

3

STA合同要求抽取消息循环。但是,是的,有可能不抽水。有两个主要的事情可能出错:

  • 是对接口方法做出从另一个公寓,其中包括另一个STA线程或MTA线程将无法完成任何呼叫。这看起来像程序中的死锁,该调用根本不会返回。当心你可以很好地控制你自己的调用,但是你不知道COM组件在做什么。它可能会启动一个线程本身。你可以在Debug + Windows + Threads的调试器中看到它。确保你在非托管模式下运行调试器,并且你可以考虑你看到的所有线程。顺便说一句,不是特别容易

  • 许多公寓线程COM组件都依赖于有一个消息循环来照顾他们自己的需要。这可能是一个无关的定时器,它不会在没有循环时打勾。或者它可能在内部进行编组。使用Spy ++并检查是否有任何隐藏的窗口拥有您的新STA线程,如果您看到其中一个,肯定会遇到麻烦。诊断仅仅是行为不当的部分。不提高事件是一种常见的事故。

当你对服务器的内部知识不够了解时,没有什么东西可以钉在墙上。一定要测试一下它。

+0

有见地的答案。非常感激。 – user12861

+0

我想我们对'CDO.Message' COM对象有类似的问题。当用户疯狂地移动MDI窗口时,它从不从'Send()'返回。可能是因为它依赖于消息队列,并且无法向其发布消息,因为它的队列完全不受所有窗口移动的影响,并且实现忘记检查“PostMessage”失败。 –

1

COM调用可以在没有消息循环的情况下编组。

当您的STA线程正在等待某件事情时,它在大多数情况下会自动处理任何挂起的COM调用。

Thread.Join文档说Blocks the calling thread [...] while continuing to perform standard COM and SendMessage pumping.

同样的情况,许多所谓代表你的其他功能(CoWaitForMultipleHandles等),如当你的线程正在等待IO。

+0

好点。感谢您的建议。 – user12861

相关问题