.net 这种情况下是否需要STA消息循环?

.net 这种情况下是否需要STA消息循环?,.net,multithreading,com,sta,.net,Multithreading,Com,Sta,我有一些COM对象正在.NET应用程序的线程上创建和运行。这些线程被标记为单线程单元,并且似乎一切正常。我的理解是,如果这些线程试图从主线程访问COM对象,那么这些对象将在.NET中自动为我进行封送和序列化,因此即使在这种情况下,事情也会为我处理,所有这些都是安全和整洁的,尽管可能有点慢 我的问题是,虽然事情似乎进展顺利,但我并没有在我正在创建的STA线程中泵送消息循环。如果可以的话,我宁愿避免消息循环,因为它会导致额外的复杂性(以及可能的效率损失) 我已经阅读了一系列关于为什么需要消息循环的建

我有一些COM对象正在.NET应用程序的线程上创建和运行。这些线程被标记为单线程单元,并且似乎一切正常。我的理解是,如果这些线程试图从主线程访问COM对象,那么这些对象将在.NET中自动为我进行封送和序列化,因此即使在这种情况下,事情也会为我处理,所有这些都是安全和整洁的,尽管可能有点慢

我的问题是,虽然事情似乎进展顺利,但我并没有在我正在创建的STA线程中泵送消息循环。如果可以的话,我宁愿避免消息循环,因为它会导致额外的复杂性(以及可能的效率损失)

我已经阅读了一系列关于为什么需要消息循环的建议(大部分来自非常有用的Hans Passant),我的理解是消息循环在线程a上提供了一个位置,其他线程B可以请求对线程a上的COM对象进行封送和处理。如果这是正确的,那么只要没有其他线程从线程A上的COM对象请求任何东西,线程在不泵送消息循环时是安全的吗?或者在其他情况下,消息循环也可能发挥作用


我是在玩火吗?有没有过这样的情况,你会问自己是否在玩火而不是在玩火?

COM调用可以在没有消息循环的情况下进行封送

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

says
的文档阻止调用线程[…],同时继续执行标准COM和SendMessage泵送。


代表您调用的许多其他函数(CoWaitForMultipleHandles等)也会发生同样的情况,例如,当您的线程正在等待IO时。

STA契约需要泵送消息循环。但是,是的,不抽水是可以逃脱的。有两件事情可能会出错:

  • 从另一单元(包括另一个STA线程或MTA中的线程)对接口方法进行的任何调用都不会完成。这看起来像是程序中的死锁,调用永远不会返回。请注意,您可以很好地控制自己的呼叫,但您不知道COM组件在做什么。它很可能会启动线程本身。您可以在调试+Windows+线程的调试器中看到这一点。确保您正在非托管模式下运行调试器,并且可以说明所看到的所有线程。顺便说一句,不是特别容易

  • 许多单元线程COM组件依赖于有一个消息循环来满足它们自己的需要。作为计时器,它可能是无害的,当没有循环时,它不会滴答作响。或者它可以在内部执行封送处理。使用Spy++并检查新STA线程是否有任何隐藏窗口,如果看到,一定会有问题的迹象。诊断结果是部件出现故障。不引发事件是常见的灾难


当您对服务器的内部结构了解不够时,就没有什么值得怀疑的了。一定要进行测试。

您有活动吗?您是否可以控制事件处理程序,以确保它们的重入调用不会导致无限递归?如果你有一个消息泵,发布消息通常用来打破这个循环。我想我不知道与此相关的问题。什么会导致在我创建的线程中引发事件而没有其他人看到?我正在使用的COM对象?据我所知,它们不会引发任何事件……如果COM对象的设计包括通知外部世界正在发生的事情,则可以实现像IConnectionPointContainer这样的传出事件接口。答案总是很有见地。非常感谢。我想我们对
CDO.Message
COM对象也有类似的问题。当用户疯狂地移动MDI窗口时,它从未从
Send()
返回。可能是因为它依赖于所说的消息队列,无法将消息发布到其中,因为队列在所有窗口移动中都已满,并且实现忘记检查
PostMessage
是否失败。