Может ли SendMessage вернуться раньше, если принимающий поток начнет перекачивать сообщения?

Как именно Windows решает, что SendMessage должен вернуться, то есть как она определяет, что принимающий поток завершил обработку отправленного сообщения?

Подробный сценарий: у меня есть поток A, использующий SendMessage для отправки потока в поток B. Очевидно, что SendMessage не возвращается, пока поток B не завершит обработку сообщения. Поток B открывает диалоговое окно и начинает закачивать сообщения. В моем сценарии в очереди есть сообщение WM_KILLFOCUS, которое перекачивается потоком B. Результатом является сообщение WM_COMMAND в потоке B. Поток B передает это сообщение WM_COMMAND процессу окна по умолчанию. Когда это происходит, SendMessage возвращается обратно в поток A, даже если исходное сообщение еще не закончило обработку! Что здесь происходит? Похоже, что процесс окна по умолчанию каким-то образом сбивает окна с толку, заставляя думать, что исходное отправленное сообщение завершено.

Итак, существуют ли известные сценарии, в которых закачка сообщений и вызов процедуры окна по умолчанию могут заставить SendMessage вернуться?

Спасибо! Фил


person Community    schedule 10.12.2009    source источник


Ответы (4)


Пока обработка сообщения начата, WindowProc, обрабатывающая межпотоковое сообщение, может вызвать ReplyMessage, чтобы позволить вызывающему потоку продолжить работу, пока продолжается обработка.

person Chris Becke    schedule 10.12.2009

Так как SendMessage имеет возвращаемое значение, оно всегда после обработки сообщения.

PostMessage, с другой стороны, не будет ждать обработки сообщения.

Из MSDN в SendMessage:

Функция SendMessage вызывает оконную процедуру для указанного окна и не возвращает значение до тех пор, пока оконная процедура не обработает сообщение.

Нет случая, когда он вернется до того, как сообщение будет обработано.

person Brian R. Bondy    schedule 10.12.2009

Судя по MSDN, проблема может заключаться в том, что отображение диалогового окна в потоке B может привести к взаимоблокировкам. См. Взаимоблокировки сообщений.


Возможно, это связано с тем, что сообщение, полученное потоком A, не было поставлено в очередь. Из MSDN:

Однако поток-отправитель будет обрабатывать входящие сообщения, не поставленные в очередь, ожидая обработки своего сообщения. Чтобы предотвратить это, используйте SendMessageTimeout с установленным SMTO_BLOCK. Дополнительные сведения о сообщениях вне очереди см. в разделе сообщения вне очереди. .

person gwell    schedule 10.12.2009

Звучит так, как будто ваш исходный SendMessage НЕ вернулся, а WindowProc в потоке A был вызван во время обработки отправленного сообщения. Нет требования, чтобы обработчик сообщений воздерживался от вызова SendMessage в ответ на получение сообщения.

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

person sean e    schedule 10.12.2009
comment
Исходный вызов SendMessage определенно возвращается. У меня есть точка останова на строке сразу после нее. Когда я достигаю этой точки останова в потоке A, поток B вызывает DefWndProc с сообщением WM_COMMAND, и он находится под обработкой исходного отправленного сообщения. Он определенно возвращается рано. - person ; 10.12.2009
comment
Я не вижу кода, но в случае точки останова в WindowProc попадание в точку останова не обязательно опровергает повторный вход. Вам нужно будет проверить стек вызовов во время попадания в точку останова, чтобы либо подтвердить, либо исключить повторный вход. Но отнеситесь к этому спокойно - у меня нет контекста/точки зрения и деталей, которые есть у вас. - person sean e; 10.12.2009