2013-08-28 313 views
1

如何在等待COM事件完成時阻止UI線程。我訂閱更新事件的COM事件已完成信號。等待COM事件完成

MyRData.OnUpdate += OnUpdate; 

我沒有自己的COM代碼,無法對其進行更改。

我試過AutoResetEvent,但阻止UI線程,我不接受來自COM的更新。

+0

你怎麼知道的COM事件是否已經完成? –

+0

@Jeroen van Langen更新了問題 – Rauld

回答

0

我終於結束了使用 Application.DoEvents()

+1

您可能需要檢查[this](http://stackoverflow.com/a/19555959/1768303),特別是'WaitWithDoEvents'。 – Noseratio

1

很可能你想在等待事件時抽出消息。爲此,MsgWaitForMultipleObjectsEx是無價的。我有一個answer(針對不同的問題),演示MsgWaitForMultipleObjectsEx的常見使用模式。

+0

你有C#示例嗎? – Rauld

+0

@EricBrown,只要我們需要抽取消息,使用'MsgWaitForMultipleObjectsEx'實際上可能比'CoWaitForMultipleHandles'更合適,因爲前者允許使用'Application.DoEvents'而不是原生的'PeekMessage/TranslateMessage/DispatchMessage'。 – Noseratio

+0

@Rauld - 我沒有真正的例子,但[PInvoke.net](http://pinvoke.net)擁有所有原生函數的簽名。 –

2

我的答案與@ EricBrown的非常相似,但有一點不同。

使用MsgWaitForMultipleObjectsEx創建nested message loop可能會導致代碼在相同線程上的重入(通過由內部PeekMessage/TranslateMessage/DispatchMessage模式分派的窗口消息)。在最糟糕的情況下,您可能最終會在前一個調用返回之前調用相同的COM對象方法之前

我會先嚐試使用CoWaitForMultipleHandlesCOWAIT_DISPATCH_CALLS(但沒有COWAIT_DISPATCH_WINDOW_MESSAGES)。如果你的COM對象是由一個out-proc服務器提供的,這很可能應該起作用。否則,你應該考慮進行一些重入檢查。我有一個related question與一些代碼顯示它可以如何完成與C#(我不得不使用COWAIT_DISPATCH_WINDOW_MESSAGES那裏,否則事件我以後沒有被解僱)。

[更新]理想情況下,你應該使用這樣的事情async/await圖案和包裝你的事件作爲一個任務(例如here's how)。我明白,有時重新使用現有的代碼來使用這種方法是不可行的。但是,如果掛起的操作需要花費相當長的時間才能完成,那麼等待其完成事件的更加用戶友好的方式可能僅僅是顯示一個模型對話框,其中包含一個很好的「請稍候...」消息(如comments中所述) 。您只需從您的事件處理程序關閉此對話框。實際上,AFAIK,這是WinForms應用程序進入嵌套消息循環的唯一支持方式。

[UPDATE]正如Eric在評論中指出的那樣,COWAIT_DISPATCH_WINDOW_MESSAGES對於STA線程是不需要的。顯然,COWAIT_DISPATCH_CALLS旨在用於新的鮮爲人知的ASTA modelhas no meaning in other apartment types

如果使用out-proc COM服務器,則無論等待線程的公寓模型如何,都會將.NET事件處理程序作爲自由線程對象進行回調(in my experience,它永遠不會是同一個STA線程, proc對象最初是創建的)。因此,等待WaitHandle.WaitOne(不抽水)應該就足夠了。但是,如果事件處理程序訪問除WaitHandle以外的任何狀態數據,則需要進行適當的同步(使用locks等)。

+2

如果代碼在STA中,則需要'COWAIT_DISPATCH_WINDOW_MESSAGES'。 [Chris Brumme的文章](http://blogs.msdn.com/b/cbrumme/archive/2004/02/02/66219.aspx)(在嵌套消息循環文章中引用)強調這一點。傳入的COM呼叫通過窗口消息到達。總的來說,我更喜歡你的解決方案(我只是*知道*在MSFT的人已經打包了MsgWaitForMultipleObjects代碼);它更乾淨簡單;但賠率是@Rauld將不得不泵。 –

+0

@EricBrown,很棒的一點,謝謝。我不知道「COWAIT_DISPATCH_CALLS」對於STA是不夠的。你提到的文章看起來是必讀的,但我忽略了它,趕上了。 – Noseratio