2016-02-22 3 views
0

Что произойдет, если я использую SendMessage() из разных потоков в один приемник? Представьте себе ситуацию, когда приемник все еще обрабатывает сообщение из Thread1, а Thread2 отправляет другое сообщение (с помощью SendMessage()). Что происходит в конце приемника? Остановляет ли он выполнение Message1, обрабатывает Message2 и после завершения Message2 возвращается в Message1 обратно? Или Message2 ждет окончания Message1?Использование SendMessage() Многопоточный

+0

Message1 _could_ выгружается во время этой обработки, если код переходит в переменное состояние ожидания, что позволит Message2 обрабатываться. Таким образом, порядок и атомарность обработки сообщений не гарантируются. –

+1

Второе сообщение отправляется, когда поток вызывает функцию обработки сообщений. –

ответ

3

Основное правило: Единственный раз, когда поток отправляет кросс-нить отосланные, при вызове сообщение-поисковой функции (GetMessage, PeekMessage и т.д.) на этой теме. Функции поиска сообщений сначала проверяют любые сообщения, передаваемые по перекрестным потокам, отправляют их один за другим, а затем переходят к извлечения сообщения из очереди сообщений потока.

Это имеет 2 последствия:

  • Cross-нить переданных сообщений автоматически рассылаются, когда принимающий поток не обрабатывает 1) любые сообщения в очереди.
  • Отправленные сообщения с перекрестными потоками отправляются, когда принимающая нить не обрабатывает 1) любое другое сообщение с перекрестным потоком.

В вашем конкретном примере приемник будет продолжать обрабатывать Message1 до завершения и перейти к отправке Message2 при следующем вызове функции поиска сообщений.

Существует одно исключение из этого правила: Поток, который ждет SendMessage для возврата может послать въездного перекрестную нить отправленные сообщения 2). Это означает, что есть потенциал для повторного входа. Повторяя ваш пример, предположим, что обработчик сообщения Message1 в какой-то момент вызывает SendMessage, вполне возможно, что Message2 отправлен до того, как обработка Message1 продолжается.

Подводя итог:

  • Cross-нить отправленные сообщения отправляются последовательно на принимающем потоке.
  • Существует несколько четко определенных времен, когда поток отправляет сообщения, переданные по перекрестным потокам.
  • Хотя сообщения с перекрестными потоками никогда не обрабатываются одновременно, нет правил атомарности; быть готовым к повторному вступлению.


1) Предполагая, что вызов сообщение-поисковая функция не является частью нормальной обработки сообщений.
2) См. When can a thread receive window messages? для получения более подробной информации о том, почему это так.

1

Я предполагаю, что вопрос заключается в том, что сообщения отправляются в конкретное окно, то есть HWND, отличное от NULL или HWND_BROADCAST, и что это окно принадлежит потоку, принадлежащему к тому же процессу.

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

Если при обработке сообщения из Thread1 принимающий поток снова вызывает GetMessage/DispatchMessage, тогда любое обрабатываемое сообщение (включая сообщения, возможно отправленные Thread2) будет обработано в этой точке, тогда управление вернется к обработке сообщения от Thread1.

Из документов для SendMessage function:

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

+0

Я всегда находил это утверждение «переключается на эту тему» ​​противоречивым. Дело в том, что это не так: он включает в себя шляпу, описанную ниже, которая не является нитью в любом смысле, а блоком и какой-то почтой. – EJP

+0

@ EJP Правильно, это немного вводит в заблуждение, как сформулировано, а чистый эффект - это то, что вы описываете. FWIW цитата приходит прямо из официальных документов MSDN, и (по быстрой проверке) она не изменилась с 2001 года. – dxiv

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