简体   繁体   中英

Wait for COM Event to complete

How do I block the UI thread while waiting for COM event to complete. I subscribe to update event of COM which signals the event has completed.

MyRData.OnUpdate += OnUpdate;

I do not own the COM code and cannot make changes to it.

I tried AutoResetEvent however that blocks the UI thread and i dont recieve updates from COM.

My answer is very similar to @EricBrown's one, but there is one different point.

Creating a nested message loop with MsgWaitForMultipleObjectsEx may lead to code reentrancy on the same thread (via a window message dispatched by the inner PeekMessage/TranslateMessage/DispatchMessage pattern). At worst scenario, you may end up calling the same COM object method before the previous call has returned.

I would first try using CoWaitForMultipleHandles with COWAIT_DISPATCH_CALLS (but without COWAIT_DISPATCH_WINDOW_MESSAGES ). In case your COM object is provided by an out-of-proc server, this most likely should work. Otherwise, you should consider putting some reentrancy checks in place.

I have a related question with some code showing how it could be done with C# (I had to use COWAIT_DISPATCH_WINDOW_MESSAGES there, otherwise the event I was after wasn't getting fired).

[UPDATE] Ideally, you should use async/await pattern for things like that and wrap your event as a task (eg here's how ). I understand, sometimes it is not feasible to re-factor existing code to use this approach. However, if a pending operation takes considerable time to complete, a more user-friendly way to wait for its completion event might be just to show a modal dialog with a nice "please wait..." message (as discussed here in comments ). You'd just close this dialog from your event handler. In fact, AFAIK, this is the only endorsed way for a WinForms app to enter a nested message loop.

[UPDATE] As Eric pointed out in comments, COWAIT_DISPATCH_WINDOW_MESSAGES is indeeded required for an STA thread. Apparently, COWAIT_DISPATCH_CALLS is intended for the new little-known ASTA model and has no meaning in other apartment types .

In case with out-of-proc COM servers, .NET event handlers are called back as free-threaded objects regardless of the waiting thread's apartment model ( in my experience , it's never the same STA thread on which the out-of-proc object was originally created). Thus, waiting with WaitHandle.WaitOne (no pumping) should be sufficient. However, if the event handler accesses any state data besides the WaitHandle , proper synchronization is required (with locks etc).

Most likely you want to pump messages while waiting for an event. For this, MsgWaitForMultipleObjectsEx is invaluable. I have an answer (to a different question) that demonstrates a common usage pattern for MsgWaitForMultipleObjectsEx .

我终于结束了使用Application.DoEvents()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM