等待COM事件完成

时间:2013-08-28 11:58:12

标签: c# .net events com message-pump

如何在等待COM事件完成时阻止UI线程。我订阅了COM的更新事件,表示事件已经完成。

MyRData.OnUpdate += OnUpdate;

我没有COM代码,也无法对其进行更改。

我尝试了AutoResetEvent但是阻止了UI线程,我没有收到来自COM的更新。

3 个答案:

答案 0 :(得分:2)

我的回答与@ EricBrown非常相似,但有一点不同。

使用MsgWaitForMultipleObjectsEx创建nested message loop可能会导致同一线程上的代码重入(通过内部PeekMessage/TranslateMessage/DispatchMessage模式调度的窗口消息)。在最糟糕的情况下,您可能最终在上一次调用返回之前调用相同的COM对象方法

我首先尝试将CoWaitForMultipleHandlesCOWAIT_DISPATCH_CALLS一起使用(但不使用COWAIT_DISPATCH_WINDOW_MESSAGES)。如果您的COM对象由一个进程外服务器提供,这很可能应该工作。否则,你应该考虑进行一些重入检查。

我有一个related question,其代码显示了如何使用C#(我必须在那里使用COWAIT_DISPATCH_WINDOW_MESSAGES,否则我之后发生的事件没有被解雇)。

[更新] 理想情况下,您应该将async/await模式用于此类事件并将您的事件包装为任务(例如here's how)。据我所知,有时重新考虑现有代码以使用这种方法是不可行的。但是,如果挂起的操作需要相当长的时间才能完成,那么等待其完成事件的一种更加用户友好的方式可能只是显示一个带有“请稍候...”消息的模态对话框(如{{ 3}})。您只需从事件处理程序关闭此对话框即可。事实上,AFAIK,这是WinForms应用程序进入嵌套消息循环的唯一认可方式。

[更新] 正如Eric在评论中指出的那样,COWAIT_DISPATCH_WINDOW_MESSAGES是STA线程所必需的。显然,COWAIT_DISPATCH_CALLS适用于新鲜鲜为人知的comments ASTA model

对于进程外COM服务器,无论等待线程的公寓模型(has no meaning in other apartment types如何),.NET事件处理程序都将作为自由线程对象回调,它永远不会出现在同一个STA线程上-of-proc对象最初创建)。因此,等待in my experience(无抽水)就足够了。但是,如果事件处理程序访问除WaitHandle之外的任何状态数据,则需要正确的同步(使用WaitHandle.WaitOne等)。

答案 1 :(得分:1)

您很可能希望在等待活动时提取消息。为此,MsgWaitForMultipleObjectsEx非常宝贵。我有一个answer(针对不同的问题)演示了MsgWaitForMultipleObjectsEx的常见用法模式。

答案 2 :(得分:0)

我终于结束了     Application.DoEvents()