2013-08-28 4 views
1

Как заблокировать поток пользовательского интерфейса при ожидании завершения COM-события. Я подписываюсь на событие обновления COM, которое сигнализирует о завершении этого события.Дождитесь завершения COM-события

MyRData.OnUpdate += OnUpdate; 

Я не являюсь владельцем COM-кода и не могу вносить в него изменения.

Я попробовал AutoResetEvent, однако блокирует поток пользовательского интерфейса, и я не получаю обновления от 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's, но есть одна другая точка.

Создание nested message loop с MsgWaitForMultipleObjectsEx может привести к повторному включению кода в том же потоке (через оконное сообщение, отправленное внутренним шаблоном PeekMessage/TranslateMessage/DispatchMessage). В худшем случае вы можете вызвать тот же метод COM-объекта до, который вернулся предыдущий вызов.

Я бы сначала попробовал использовать CoWaitForMultipleHandles с COWAIT_DISPATCH_CALLS (но без COWAIT_DISPATCH_WINDOW_MESSAGES). В случае, если ваш объект COM предоставлен сервером вне очереди, это, скорее всего, будет работать. В противном случае вам стоит подумать о том, чтобы поместить некоторые проверки на повторную регистрацию.

У меня есть related question с некоторым кодом, показывающим, как это можно сделать с помощью C# (мне пришлось использовать COWAIT_DISPATCH_WINDOW_MESSAGES, иначе событие, в котором я был, не уволялось).

[UPDATE] В идеале, вы должны использовать async/await шаблон для вещей, как, что и обернуть событие как задача (например here's how). Понимаю, иногда невозможно переоценить существующий код для использования этого подхода. Однако, если ожидающая операция занимает много времени для завершения, более удобный для пользователя способ дождаться ее события завершения может состоять в том, чтобы просто показать модальный диалог с хорошим сообщением «please wait ...» (как описано здесь в comments) , Вы просто закроете это диалоговое окно от своего обработчика событий. Фактически, AFAIK, это единственный одобренный способ для приложения WinForms ввести вложенный цикл сообщений.

[ДОПОЛНЕНО] Как отметил Эрик в комментариях, COWAIT_DISPATCH_WINDOW_MESSAGES действительно требуется для резьбы STA. По-видимому, COWAIT_DISPATCH_CALLS предназначен для новых малоизвестных ASTA model и has no meaning in other apartment types.

В случае, если COM-серверы вне лицензии, обработчики событий .NET вызываются обратно как объекты с бесплатной резьбой независимо от модели квартиры ожидающего потока (in my experience, это никогда не те же потоки STA, объект proc был создан). Таким образом, ожидания с WaitHandle.WaitOne (без перекачки) должны быть достаточными. Однако, если обработчик событий получает доступ к любым данным состояния, кроме WaitHandle, необходима правильная синхронизация (с locks и т. Д.).

+2

Если код находится в STA, требуется 'COWAIT_DISPATCH_WINDOW_MESSAGES'. [Статья Криса Брумме] (http://blogs.msdn.com/b/cbrumme/archive/2004/02/02/66219.aspx) (упоминается в вашей вложенной статье цикла сообщений) подчеркивает это. Входящие COM-вызовы поступают через оконные сообщения. В целом, я предпочитаю ваше решение (я просто * знал, что кто-то в MSFT уже упаковал код MsgWaitForMultipleObjects); это чище и проще; но шансы @Rauld придется перекачивать. –

+0

@ EricBrown, отличный момент, спасибо. Я не знал, что для STA недостаточно COWAIT_DISPATCH_CALLS. Статья, которую вы упомянули, выглядит обязательной, но я ее не замечаю, догоняю. – Noseratio

Смежные вопросы