Почему модальные диалоги, которые открываются через событие щелчка элемента меню, обрабатывают все сообщения окна?

Так что в течение последнего дня я исправлял ошибку, вызванную модальным диалогом. Я работаю над приложением, которое связывается с сервером через насос сообщений Windows. Когда я использую ShowDialog() для показа модальной формы, насос сообщений блокируется, и ни одно из моих сообщений не обрабатывается, но они накапливаются в очереди (ожидаемое поведение).

Однако недавно я заметил, что если модальная форма открывается через событие щелчка элемента меню, сообщения перекачиваются в основную форму и обрабатываются. Кто-нибудь знает, почему эти сообщения не блокируются, когда модальная форма отображается через событие нажатия элемента меню?

РЕДАКТИРОВАТЬ: я должен был отметить, что я использую C#. Как насчет этого; если никто не может ответить на этот вопрос, может кто-нибудь сказать мне, как исследовать это сам? Единственное, о чем я могу думать, это посмотреть на стек вызовов. К сожалению, это еще ничего мне не сказало.

7 ответов

Попробуйте установить того же владельца / родителя для диалогового окна из меню в диалоговое окно, в котором показано ожидаемое поведение при прокачке сообщений.

Да, я вызываю ShowDialog() из события щелчка пункта меню. В этом случае сообщения перекачиваются через модальный диалог в основную форму.

В целом, ваш клиентский интерфейс не должен блокироваться для длительных операций на сервере. .Net упрощает работу сервера с использованием потока BackgroundWorker. Смотрите этот пост для примера: многопоточный импорт

Пример в VB, но вы можете перейти по ссылкам для примера C#.

Вы вызываете ShowDialog() из события click или каким-либо другим способом?

Какой вид управления меню вы используете? Может ли он выполняться в отдельном потоке от того, где работает основная форма?

@Chris: я просто использую стандартный элемент управления MenuStrip. Если бы он работал в отдельном потоке, мне было бы интересно, как он отображает форму как модальную. Я экспериментировал с показом диалога из отдельного потока, чтобы не блокировать очередь сообщений, но я не могу указать основную форму как родительскую, поэтому она не является модальной.

Мне не совсем понятно, что вы подразумеваете под «сообщением о заблокированном насосе».

Что происходит, так это то, что ShowDialog не возвращается, поэтому насос сообщений верхнего уровня ожидает, пока ваше приложение вернется из обработки любого события, заставившего его вызвать ShowDialog; это ничем не отличается от того, если бы ваш обработчик для этого даже перемалывал процессор. Так что да, в этом смысле насос сообщений заблокирован.

Но сам модальный диалог запускает свой собственный цикл перекачки сообщений до тех пор, пока диалог не будет закрыт, который должен обрабатывать сообщения так же, как и основной цикл, поэтому я не понимаю, почему какие-либо сообщения должны накапливаться в очереди.

Этот цикл обработки сообщений обрабатывает сообщения для всех окон, потому что он должен, например, позволить другим окнам приложения правильно рисовать себя.

Вы можете попробовать просмотреть стек обратного вызова (от вызова ShowDialog до корня стека) и сравнить, как он выглядит, когда «все работает как надо» и когда «все не работает». Это может быть что-то тонкое, например, получили ли вы вызов ShowDialog через отправку сообщений или предварительную обработку сообщений (что, как я только что обнаружил, имеет значение, когда вы вызываете ContextMenuStrip.Show)

Другие вопросы по тегам