Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Событийная модель Windows (http://forum.oszone.net/showthread.php?t=74504)

CyraxZ 13-11-2006 11:28 510890

Событийная модель Windows
 
Почитал доки по событиям Windows. Везде пишут по теме с точки зрения прикладного программиста, т.е. "получил сообщение", "обработал событие" и т.п. А что конкретно делают потоки и процессы при этом (и какие потоки и процессы) - об этом ни слова...

Пока сложилась следующая картина:
1. При возникновении прерываний от железа аппаратно вызываются соответствующие обработчики.
2. (а вот здесь не понятно, что далее делают эти обработчики (стандартные) и что происходит до момента, когда ось начинает отправлять сообщения приложениям).
3. ОС записывает информацию о произошедшем событии (т.е. посылает сообщение) всем запущенным приложениям (естественно только о тех событиях, которые должны обрабатывать GUI-приложения) в очереди сообщений (message queue).
4. Главные потоки приложений циклически проверяют свой буфер (очередь) сообщений и если там обнаруживается информация о произошедшем событии, то вызывается главный обработчик событий приложения (например, OnMessage объекта Application).
5. Главный обработчик событий приложения сам обрабатывает это событие, затем по очереди вызывает обработчики
DefWindowProc всех графических элементов приложения, находящихся в непосредственном владении приложения, в частности (и обычно) главного окна приложения.
6. Затем свои обработчики DefWindowProc этих подчинённых графических элементов сами обрабатывают событие и по очереди вызывают обработчики DefWindowProc уже своих подчинённых графических элементов (например, кнопки на форме) и т.д.
7. Обработчики DefWindowProc всех графических элементов приложения в зависимости от события и наличия обработчиков этих событий вызывают эти обработчики (код которых и пишут прикладные программисты).

Ну вот, приблизительно всё так, но в то же время и не так...

8)__________________________________________________
Ну, и вопрос по фоновым процессам.
Если обработка очереди сообщения приложения происходит в цикле (т.е. главный поток приложения всё время работает), то потоки фоновых процессов (у которых самый низкий приоритет) вообще не будут выполняться...

DillerInc 13-11-2006 12:57 510932

Цитата:

то потоки фоновых процессов (у которых самый низкий приоритет) вообще не будут выполняться...
...а как же многозадачность??
Цитата:

Цитата В.И.Юров
Windows поддерживает очередь сообщений для каждого приложения.Запуск приложения автоматически подразумевает формирование для него собственной очереди сообщений...


ivank 13-11-2006 14:22 510992

Цитата:

4. Главные потоки приложений циклически проверяют свой буфер (очередь) сообщений и если там обнаруживается информация о произошедшем событии, то вызывается главный обработчик событий приложения (например, OnMessage объекта Application).
5. Главный обработчик событий приложения сам обрабатывает это событие, затем по очереди вызывает обработчики
DefWindowProc всех графических элементов приложения, находящихся в непосредственном владении приложения, в частности (и обычно) главного окна приложения.
6. Затем свои обработчики DefWindowProc этих подчинённых графических элементов сами обрабатывают событие и по очереди вызывают обработчики DefWindowProc уже своих подчинённых графических элементов (например, кнопки на форме) и т.д.
7. Обработчики DefWindowProc всех графических элементов приложения в зависимости от события и наличия обработчиков этих событий вызывают эти обработчики (код которых и пишут прикладные программисты).

Ну вот, приблизительно всё так, но в то же время и не так...

8)__________________________________________________
Ну, и вопрос по фоновым процессам.
Если обработка очереди сообщения приложения происходит в цикле (т.е. главный поток приложения всё время работает), то потоки фоновых процессов (у которых самый низкий приоритет) вообще не будут выполняться...
Не так. Есть одна системная очередь, а так же у каждого потока своя очередь сообщений (если поток создаёт хотя бы одно окно, то эта очередь автоматически создаётся. По умолчанию её нет) и свой цикл GetMessage/DispatchMessage). Каждый системный (например, окно) объект создаётся в неком потоке, ему он и принадлежит, и все его сообщения идут именно в этот поток.

Затем, никакого "главного" обработчика событий (кроме цикла выборки сообщений из очереди потока) нет. DispatchMessage высылает сообщение сразу соответствующему обработчику. DefWindowProc - это вообще стандартная функция (как ни странно, для реализации поведения окна "по умолчанию"). Из твоего кода она вызывать ничего никогда не будет (но может послать некие события).

Для реализации "красивого" апи окошек C++ Builder делает нечто похожее на следующее. Создаёт свою оконную процедуру, которой будут поступать все сообщения окна. Затем с помощью GetWindowLong получает указатель на объект формы, которой это окно является. Если пришедшее сообщение соответствует некому обработчику (например WM_KEYDOWN -> OnKeyDown), то вызывает соответствующий метод объекта и возвращает 0. Иначе вызывает DefWindowProc для реализации поведения по умолчанию. (Примерно так. Билдер даже никогда не щупал, но принципиально по другому и не сделаешь).

Цитата:

Если обработка очереди сообщения приложения происходит в цикле (т.е. главный поток приложения всё время работает), то потоки фоновых процессов (у которых самый низкий приоритет) вообще не будут выполняться...
Есть такая штука как вытесняющая многозадачность. Как бы поток не хотел что-нибудь делать, когда придёт время - обязательно даст и другим поделать. И даже потоки самых низких приоритетов получают чуточку времени (чем ниже приоритет, тем меньше, логично). Да и в эпоху кооператичной многозадачности первый же вызов некой системной функции приводил к смене потока, если она должна была быть.

Кстати, вот что нашёл: http://winpro.narod.ru/Messages.htm Достаточно популярное объяснение.

CyraxZ 13-11-2006 21:06 511198

Цитата:

Поток может использовать функцию WaitMessage, для того, чтобы передать управление другим потокам, пока в его очереди сообщений нет никаких сообщений. Эта функция останавливает работу потока и не возобновляет ее до появления нового сообщения в очереди сообщений потока.
А есть ли смысл продолжать работу потока, когда в его очереди сообщений нет последних ?
Т.е. почему бы всегда не останавливать работу потока до появления новых сообщений (т.е. до тех пор, пока очередь сообщений станет непустой) ?
Ведь во фрагменте кода потока, где циклически проверяется очередь сообщений, никаких других действий, кроме проверки этой очереди, не происходит. Т.е. цикл будет крутиться впустую...

Цитата:

Если поток получает ввод с клавиатуры, то цикл сообщений должен иметь функцию TranslateMessage. Система генерирует сообщения виртуальных клавиш (WM_KEYDOWN и WM_KEYUP) при каждом нажатие клавиши пользователем. Сообщение виртуальной клавиши содержит код виртуальной клавиши, который показывает какая, была нажата клавиша (а не ее символьное значение). Функция TranslateMessage переводит сообщение виртуальной клавиши в символьное сообщение (WM_CHAR) и помещает его обратно в очередь сообщений приложения. Это символьное сообщение будет извлечено на следующей итерации цикла сообщения и передано оконной процедуре.
Правильно ли я понял, что сообщения виртуальных клавиш посылаются системой в очередь сообщений только одного потока, соответствующего активному окну (т.е. неактивные окна это сообщение не получают) ?

Цитата:

Приложение, использующее акселераторные клавиши должно переводить клавиатурные сообщения в командные. Для этого цикл сообщения должен содержать вызов функции TranslateAccelerator.
Акселераторные клавиши - это какие ?
___________________________________
И как быть с событиями неграфических объектов (т.е. не имеющих графического представления и, следовательно, не имеющих дескрипторов), например, в Delphi или C++ Builder (которые шлёпают мышой на форму)? Должно быть, эти события - не что иное, как обычный вызов обработчиков (методов объекта) из других методов этих объектов. Т.е. никаких манипуляций с очередями сообщений потоков здесь не происходит...

CyraxZ 13-11-2006 21:18 511203

Фрагмент одной статьи:
Цитата:

Процессы с фоновым приоритетом запускаются лишь в том случае, если в очереди Диспетчера задач нет других процессов. Обычные виды приложений, использующие такой приоритет, — это программы-заставки и системные агенты (system agents). Программисты могут использовать фоновые процессы для организации завершающих операций и реорганизации данных. Примерами могут служить автосохранение документа или базы данных.
Что значит "в очереди Диспетчера задач нет других процессов" ?
Для любого окна выполняется код обработки сообщений соответствующего потока (даже если нет сообщений, крутится вхолостую). Чем не претендент на очередь диспетчера...

DillerInc 14-11-2006 00:35 511281

Цитата:

Правильно ли я понял, что сообщения виртуальных клавиш посылаются системой в очередь сообщений только одного потока, соответствующего активному окну
...да,согласно следующей цитате:
Цитата:

Цитата MSDN
The system posts keyboard messages to the message queue of the foreground thread that created the window with the keyboard focus.

А вообще вот информация к размышлению -- UserInput -- там и про акселераторы есть.

pva 16-11-2006 08:27 512384

Цитата:

даже если нет сообщений, крутится вхолостую
неправда, почитайте любую апишную справку. GetMessage не возвращается, пока не поступит хоть одно сообщение (работа потока блокируется и ему не выделяются кванты времени процессора) Хочется поподробней? почитайте раздел "синхронизация" в MSDN или win32.hlp, который вместе с борландом идёт
Цитата:

И как быть с событиями неграфических объектов (т.е. не имеющих графического представления и, следовательно, не имеющих дескрипторов),
как правило, они прицепляются к тем, у кого есть. А те, в свою очередь, так уж и быть, делятся своими событиями. Например, TAction вы гидаете на TForm, которая события получает.


Время: 13:42.

Время: 13:42.
© OSzone.net 2001-