пользователей: 30398
предметов: 12406
вопросов: 234839
Конспект-online
РЕГИСТРАЦИЯ ЭКСКУРСИЯ

Оконные сообщения. Базовые принципы. Асинхронная посылка сообщений

lРазрабатывая подсистему управления окнами в Windows 2000 и Windows 98, Microsoft преследовала две основные цели:
lобратная совместимость с 16-разрядной Windows, облегчающая перенос существующих 16-разрядных приложений,
lотказоустойчивость подсистемы управления окнами, чтобы ни один поток не мог нарушить работу других потоков в системе.
lэти цели прямо противоречат друг другу.
lВ 16-разрядной Windows передача сообщения в окно всегда осуществляется синхронно: отправитель не может продолжить работу, пока окно не обработает полученное сообщение.
lНо, если на обработку сообщения потребуется длительное время или если окно «зависнет», выполнение отправителя просто прекратится. А значит, такая операционная система не вправе претендовать на устойчивость к сбоям.
lОдин процесс в Windows может создать до 10 000 User-объектов различных типов — значков, курсоров, оконных классов, меню таблиц, клавиш-акселераторов и т.д.
lКогда поток из какого-либо процесса вызывает функцию, создающую один из этих объектов, последний переходит во владение процесса.
lПоэтому, если процесс завершается, не уничтожив данный объект явным образом, операционная система делает это за него.
lОднако два User-объектa (окна и ловушки) принадлежат только создавшему их потоку. И вновь, если поток создает окно или устанавливает ловушку, а потом завершается, операционная система автоматически уничтожает окно или удаляет ловушку.
lЭтот принцип принадлежности окон и ловушек создавшему их потоку оказывает существенное влияние на механизм функционирования окон: поток, создавший окно, должен обрабатывать все его сообщения. 
lДопустим, поток создал окно, а затем прекратил работу. Тогда его окно уже не получит сообщение WM_DESTROY или WM_NCDESTROY, потому что поток уже завершился и обрабатывать сообщения, посылаемые этому окну, больше некому.
lЭто также означает, что каждому потоку, создавшему хотя бы одно окно, система выделяет очередь сообщений, используемую для их диспетчеризации.
lЧтобы окно в конечном счете получило эти сообщения, поток должен иметь собственный цикл выборки сообщений.
lС этой целью ОС создает на каждый поток собственную очередь синхронных сообщений(sent-message queue), очередь асинхронных сообщений (post-message queue), очередь ответных сообщений (reply-message queue) и др.
lЭти очереди реализованы в виде двусвязного списка.
 
lКогда с потоком связывается структура THREADINFO, он получает свой набор очередей сообщений. Если процесс создает три потока и все они вызывают функцию Create Window, то и наборов очередей сообщений будет тоже три. Сообщения ставятся в очередь асинхронных сообщений вызовом функции PostMessage:

BOOL PostMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

lПри помощи этой функции можно поставить сообщение Msg с параметрами wParam и lParam в очередь асинхронных сообщений потока, которому принадлежит окно hWnd. 
lВозврат из функции происходит сразу же после постановки сообщения в очередь. Вызывающий поток "понятия не имеет" обработано сообщение или нет. Функция возвращает TRUE, если сообщение удачно поставлено в очередь. На самом деле вполне вероятно, что окно даже не получит это сообщение. Такое возможно, если поток, создавший это окно, завершится до того, как обработает все сообщения из своей очереди. 
lСообщение можно поставить в очередь асинхронных сообщений потока и вызовом PostThreadMessage:

BOOL PostThreadMessage(DWORD dwThreadId, UINT uMsg, WPARAM wParam, LPARAM lParam);

lНужный поток идентифицируется первым параметром, dwThreadId.
lЭта функция применяется, когда приложение выполняет какую-то особую обработку в основном цикле выборки сообщений потока.
lКак и PostMessage, функция PostThreadMessage возвращает управление сразу после того, как сообщение поставлено в очередь потока. И вновь вызывающий поток остается в неведении о дальнейшей судьбе сообщения.
lКакой поток создал окно, можно определить с помощью:

DWORD GetWindowThreadProcessId( HWND hwnd, PDWORD pdwProcessId);

lОна возвращает уникальный общесистемный идентификатор потока, который создал окно, определяемое параметром hwnd. Передав адрес переменной типа DWORD в параметре pdwProcessId, можно получить и уникальный общесистемный идентификатор процесса, которому принадлежит этот поток. Но обычно такой идентификатор не нужен, и мы просто передаем NULL.
lЕще одна функция, позволяющая поместить сообщение в очередь асинхронных сообщений потока:

VOID PostQuitMessage(int nExilCode);

lОна вызывается для того, чтобы завершить цикл выборки сообщений потока. Ее вызов аналогичен вызову

PostThreadMessage(GetCurrentThreadId(), WM_QUIT, hExitCode, 0);

 


26.12.2015; 23:28
хиты: 0
рейтинг:0
для добавления комментариев необходимо авторизироваться.
  Copyright © 2013-2024. All Rights Reserved. помощь