如何在C#中为COM STA线程泵送消息?
我有一个主STA线程,在COM对象上调用很多方法,还有一个辅助STA线程,在同一个对象上也做很多工作。我希望主线程和次线程并行工作(即,我期望主线程和次线程的交错输出)。我知道我需要不时地在主线程中发送消息——用C++调用get /平移/调度消息将起到作用。 但我在C#中使用相同的策略时遇到了问题。首先,我在主线程中使用CurrentThread.Join()来控制第二个线程。它不起作用。然后我转向Application.DoEvents()——每当我想让第二个线程运行时,我就在主线程中调用它。结果是第二个线程很快就抓住了控件,并且不会放手——直到第二个线程全部完成,主线程才能继续 我阅读的文档中说Application.DoEvents()将处理所有等待的事件,而GetMessage()只检索一条消息 正确的做法是什么?是否有C#等效于Get/Translate/DispatchMessage 谢谢 更新:第二个线程运行太快,向主STA线程发送大量COM调用消息。我只是在第二个线程中添加了延迟来降低速度。现在两个线程基本上是并行运行的。如何在C#中为COM STA线程泵送消息?,c#,com,message,sta,doevents,C#,Com,Message,Sta,Doevents,我有一个主STA线程,在COM对象上调用很多方法,还有一个辅助STA线程,在同一个对象上也做很多工作。我希望主线程和次线程并行工作(即,我期望主线程和次线程的交错输出)。我知道我需要不时地在主线程中发送消息——用C++调用get /平移/调度消息将起到作用。 但我在C#中使用相同的策略时遇到了问题。首先,我在主线程中使用CurrentThread.Join()来控制第二个线程。它不起作用。然后我转向Application.DoEvents()——每当我想让第二个线程运行时,我就在主线程中调用它。
但我仍然想知道是否有C等价于GETMeals/TrimeMeSea/Debug Cuff.< /P> < P>您原来的C++代码违反了STA合同。它表示必须将接口指针从一个线程封送到另一个线程,以便仅从一个线程对对象进行所有调用。对于单线程COM服务器来说,这是一个困难的要求,不这样做会带来与多线程对非线程安全代码进行调用相关的典型痛苦。使用两个STA线程并不能免除此要求,对象仅由创建它的线程拥有。第二个线程只是另一个线程,无法安全地进行调用,因为服务器不支持多线程 你不知怎么地在C++代码中侥幸逃脱了,很难想象不时有毛病。COM不能在进程内COM服务器上强制执行STA协定,只能在进程外服务器上强制执行STA协定。在这种情况下,违反合同会生成RPC_E_错误的线程 不管怎样,你再也不能在C#程序中侥幸逃脱了。CLR会自动为您封送接口指针。您在第二个线程上进行的调用将被封送到拥有该对象的STA线程。仍然存在交错,但只有当第一个线程空闲并重新进入消息循环时,才能传递第二个线程的调用。没有解决方法,接口指针的CLR处理严格按照规则进行
我想这会给你的代码带来很多后果,最大的一个后果是第二个线程真的不能完成任何事情了。没有并发性,对对象的所有调用都严格序列化。而且是线程安全的。您最好只从一个线程进行所有调用,这样您就不必担心死锁带来的巨大风险。作为奖励,让适当的信息传递变得不那么重要。如果第二个线程执行其他关键工作,那么利用COM对单线程代码的支持会很有帮助。在.Net中获取/翻译/分派时,您应该能够调用或(取决于您使用的是winforms还是wpf)帮助线程。这将在调用Get/Trans/Dispatch的线程上为您泵送一个消息循环。如果您不喜欢这种想法,那么您可以P/调用Win32调用
尽管.Net会根据答案让几乎所有的东西都能为您工作,但实际上我发现来自COM对象的消息可能会导致UI线程结巴,因为底层的DispatchMessage()似乎需要很长时间(当然比我预期的要长,或者可以解释)。我们改变了解决方案,在helper线程上创建COM对象,并显式地从UI线程封送对它的调用嗨,汉斯,我不只是侥幸逃脱——我使用的是C++接口的全局接口表来进行编组。对于C#,CLR在内部为我进行编组。另外,我知道STA模型中没有真正的并发性,因为所有调用都是在单元中序列化的。不管怎样,现在看起来两个线程并行运行,这就是我想要的。但是现在我真的怀疑STA多线程的意义是什么——它能实现什么吗?嗯,“交错”让我走上了错误的轨道。那么,C代码没有理由表现出任何不同。不要使用Thread.Join(),除非您希望实际等待第二个线程完成。顺便说一句,COM线程支持的要点是,您(几乎)可以完全忽略在多个线程中使用非线程安全代码。根本不需要锁。NET并没有类似的功能。“几乎”当然是难点。嗨,汉斯,谢谢你指出这一点。顺便说一句,我使用CurrentThread.Join()的原因是这篇文章:。“如果必须使用STA线程来创建COM组件,则STA线程必须定期泵送消息。若要短时间泵送消息,请调用Thread.Join方法,如下所示:Thread.CurrentThread.Join(100)”@Charlie。这一点一开始也让我大吃一惊,但如果你能正常地运行消息循环,你的代码最终会变得更干净。那篇kb文章是对控制台模式程序的攻击。它们没有消息循环。使用Join()是愚蠢的,只需将其设置为[MTAThread]就足以迫使COM为COM组件创建STA线程,为其提供一个友好的家。尽管现在每一个电话都会被处理。你肯定已经在你的主线程泵?