Что произойдет, если я использую SendMessage() из разных потоков в один приемник? Представьте себе ситуацию, когда приемник все еще обрабатывает сообщение из Thread1, а Thread2 отправляет другое сообщение (с помощью SendMessage()). Что происходит в конце приемника? Остановляет ли он выполнение Message1, обрабатывает Message2 и после завершения Message2 возвращается в Message1 обратно? Или Message2 ждет окончания Message1?Использование SendMessage() Многопоточный
ответ
Основное правило: Единственный раз, когда поток отправляет кросс-нить отосланные, при вызове сообщение-поисковой функции (GetMessage, PeekMessage и т.д.) на этой теме. Функции поиска сообщений сначала проверяют любые сообщения, передаваемые по перекрестным потокам, отправляют их один за другим, а затем переходят к извлечения сообщения из очереди сообщений потока.
Это имеет 2 последствия:
- Cross-нить переданных сообщений автоматически рассылаются, когда принимающий поток не обрабатывает 1) любые сообщения в очереди.
- Отправленные сообщения с перекрестными потоками отправляются, когда принимающая нить не обрабатывает 1) любое другое сообщение с перекрестным потоком.
В вашем конкретном примере приемник будет продолжать обрабатывать Message1 до завершения и перейти к отправке Message2 при следующем вызове функции поиска сообщений.
Существует одно исключение из этого правила: Поток, который ждет SendMessage для возврата может послать въездного перекрестную нить отправленные сообщения 2). Это означает, что есть потенциал для повторного входа. Повторяя ваш пример, предположим, что обработчик сообщения Message1 в какой-то момент вызывает SendMessage
, вполне возможно, что Message2 отправлен до того, как обработка Message1 продолжается.
Подводя итог:
- Cross-нить отправленные сообщения отправляются последовательно на принимающем потоке.
- Существует несколько четко определенных времен, когда поток отправляет сообщения, переданные по перекрестным потокам.
- Хотя сообщения с перекрестными потоками никогда не обрабатываются одновременно, нет правил атомарности; быть готовым к повторному вступлению.
1) Предполагая, что вызов сообщение-поисковая функция не является частью нормальной обработки сообщений.
2) См. When can a thread receive window messages? для получения более подробной информации о том, почему это так.
Я предполагаю, что вопрос заключается в том, что сообщения отправляются в конкретное окно, то есть HWND, отличное от NULL или HWND_BROADCAST, и что это окно принадлежит потоку, принадлежащему к тому же процессу.
В этом случае поток, создавший целевое окно, получит сообщение в следующий раз, когда GetMessage вызывается с фильтром, который включает данное окно. Отправляющий поток будет заблокирован до тех пор, пока принимающий поток не завершит обработку сообщения.
Если при обработке сообщения из Thread1 принимающий поток снова вызывает GetMessage/DispatchMessage, тогда любое обрабатываемое сообщение (включая сообщения, возможно отправленные Thread2) будет обработано в этой точке, тогда управление вернется к обработке сообщения от Thread1.
Из документов для SendMessage function:
Если указанное окно было создано вызывающим потоком, оконная процедура вызывается непосредственно в качестве подпрограммы. Если указанное окно было создано другим потоком, система переключается на этот поток и вызывает соответствующую процедуру окна. Сообщения, отправленные между потоками, обрабатываются только тогда, когда принимающий поток выполняет код поиска сообщений. Посылающий поток блокируется до тех пор, пока принимающий поток не обработает сообщение.
Я всегда находил это утверждение «переключается на эту тему» противоречивым. Дело в том, что это не так: он включает в себя шляпу, описанную ниже, которая не является нитью в любом смысле, а блоком и какой-то почтой. – EJP
@ EJP Правильно, это немного вводит в заблуждение, как сформулировано, а чистый эффект - это то, что вы описываете. FWIW цитата приходит прямо из официальных документов MSDN, и (по быстрой проверке) она не изменилась с 2001 года. – dxiv
- 1. Правильное использование SendMessage() и PostMessage()
- 2. :: SendMessage()
- 3. Использование SendMessage для имитации щелчков мыши пользователя
- 4. Многопоточный эхо-сервер
- 5. Многопоточный PHP и многопоточный Python
- 6. Повторное использование OpenSSL-сеанса Многопоточный сбой
- 7. PostThreadMessage & SendMessage
- 8. windows - sendmessage
- 9. многопоточный предел?
- 10. Использование АХК PostMessage/SendMessage или DllCall («SendMessage», чтобы получить содержимое элемент списка
- 11. Многопоточный многопользовательский чат-сервер
- 12. SendMessage исчезает в эфире
- 13. Многопоточный загрузчик в C#
- 14. Многопоточный прием JMS весной
- 15. Многопоточный python
- 16. Многопоточный QuickSort
- 17. C++ многопоточный
- 18. Многопоточный отладчик
- 19. Многопоточный Z3?
- 20. Многопоточный JDBC
- 21. многопоточный вектор
- 22. Многопоточный дизайн
- 23. Многопоточный Haskell
- 24. многопоточный сервер
- 25. Многопоточный метод
- 26. Многопоточный BIOS
- 27. Многопоточный выпуск
- 28. многопоточный QSqlQuery
- 29. Многопроцессорный и многопоточный дизайн
- 30. Пользовательский многопоточный контур
Message1 _could_ выгружается во время этой обработки, если код переходит в переменное состояние ожидания, что позволит Message2 обрабатываться. Таким образом, порядок и атомарность обработки сообщений не гарантируются. –
Второе сообщение отправляется, когда поток вызывает функцию обработки сообщений. –