如何在C#中为COM STA线程提取消息?

Cha*_*lie 5 c# com message sta doevents

我有一个主要的STA线程,它调用COM对象上的很多方法,以及一个辅助STA线程,它也在同一个对象上做了很多工作.我希望主线程和辅助线程并行工作(即我希望主要和次要的隔行扫描输出).我知道我需要时不时地在主线程中抽取消息 - 在C++中调用Get/Translate/DispatchMessage就可以了.

但是我遇到了在C#中使用相同策略的问题.起初我在主线程中使用CurrentThread.Join()来控制第二个线程.它没用.然后我转向Application.DoEvents() - 每当我想要第二个线程运行时,我在主线程中调用它.结果是第二个线程快速抓取控件并且不会松开 - 主线程无法继续直到第二个线程全部完成.

我阅读的文档说Application.DoEvents()将处理所有等待事件 - 而GetMessage()只检索一条消息.

什么是正确的做法?是否有C#等价的Get/Translate/DispatchMessage?

谢谢

更新:第二个线程运行得太快,向主STA线程发送大量COM调用消息.我刚刚在第二个线程中添加了延迟以减慢速度.现在两个线程基本上并行运行.但我仍然想知道是否存在与G#等效的GetMessage/TranslateMessage/DispatchMessage.

Han*_*ant 7

您的原始C++代码违反了STA合同.这表明接口指针必须从一个线程封送到另一个线程,以便对象上的所有调用都只来自一个线程.这是单线程COM服务器的一项硬性要求,但这样做不会带来与在线程安全的代码上从多个线程调用make相关的典型痛苦.使用两个STA线程并不能解除您的要求,该对象仅由创建它的线程拥有.第二个线程只是另一个线程,由于服务器不支持多线程,因此无法安全地进行调用.

你在C++代码中以某种方式逃脱了它,很难想象偶尔会有一个小故障.COM无法在进程内COM服务器上强制执行STA合同,仅在进程外服务器上执行.在这种情况下,违反合同会生成RPC_E_WRONG_THREAD.

Anyhoo,你不再在C#程序中侥幸逃脱.CLR会自动为您编组接口指针.您在第二个线程上进行的调用将被封送到拥有该对象的STA线程.仍然存在交错,但第二个线程的调用只能在第一个线程空闲并重新进入消息循环时传递.没有解决方法,接口指针的CLR处理严格遵循规则.

这将对我想象的代码产生很多影响,最大的一个是第二个线程真的不再能完成任何事情了.没有并发性,对对象的所有调用都是严格序列化的.并且线程安全.你可能最好只是从一个线程进行所有调用,这样你就不必为死锁带来相当大的风险.作为奖励,使正确的消息流动不那么重要.如果第二个线程执行其他关键工作,那么利用COM支持单线程代码可能会有所帮助.

  • 嗯,'交错'让我走错了路.那么,没有理由让C#代码表现出任何不同.除非您想要实际等待第二个线程完成,否则不要使用Thread.Join().它泵了一个消息循环btw.COM线程支持的关键在于您(几乎)可以完全忽略您在多个线程中使用非线程安全代码.根本不需要锁定..NET没有相同的东西.当然,"差不多"就是摩擦. (3认同)
  • 嗨汉斯,我不只是逃避它 - 我正在使用C++代码中的全局接口表来进行编组.对于C#,CLR正在为我内部编组.另外我理解STA模型中没有真正的并发性,因为所有的调用都是在公寓中序列化的.无论如何现在似乎两个线程并行运行,这就是我想要的.但现在我怀疑STA多线程的重点是什么 - 它是否实现了任何目标? (2认同)