Мой ответ очень похож на @ 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 и т. Д.).
Как вы знаете, что COM событие является полным? –
@Jeroen van Langen Обновлено Вопрос – Rauld