Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Обучение VC++ / ЛекцииИнтернетС++ / Лекция_лаб_практикум.doc
Скачиваний:
64
Добавлен:
16.02.2016
Размер:
932.35 Кб
Скачать

Передача управления

Что произойдет, если одна из функций-обработчиков окажется “жадной” и израсходует 10 секунд процессорного времени? Во времена 16-разрядной системы компьютер просто завис бы на это время. Разве что можно было бы перемещать курсор мыши, да исполнялись бы какие-то задачи, управляемые прерываниями. В Win32 многозадачность организована куда лучше. Благодаря вытесняющей многозадачности другие приложения не зависнут — Windows, когда сочтет это нужным, просто приостановит выполнение “жадной” функции. Однако даже в Win32 ваша программа на эти 10 секунд была бы заблокирована. Она не смогла бы обрабатывать какие-либо сообщения, так как DispatcbMessage не возвращает управление до тех пор, пока его не возвратит злополучный обработчик.

Однако есть способ обойти эту проблему. Он срабатывает как в Winl6, так и в Win32. Надо просто заставить “жадную” функцию вести себя дружелюбнее, т. е. периодически отдавать управление — а для этого вставить в ее основной цикл такие операторы:

MSG message;

if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE))

{

::TranslateMessage(&message);

::DispatchMessage(&fflessage);

}

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

Таймеры

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

Для работы с таймерами необходимо вызывать функцию CWnd::SetTimer с параметром — интервал времени, после чего с помощью ClassWizard нужно определить обработчик сообщения WM_TIMER. После запуска таймера с заданным интервалом в миллисекундах сообщения WM_TIMER постоянно посылаются окну приложения до тех пор, пока не будет вызвана CWnd::KillTiiner или уничтожено окно. При необходимости можно задействовать несколько таймеров, каждый из которых идентифицируется целым числом. Поскольку Windows не является операционной системой реального времени, интервал значительно менее 100 миллисекунд приводит к потере точности.

Подобно другим сообщениям Windows, сообщения таймера могут заблокировать другие функции-обработчики в программе. К счастью, сообщения таймера не аккумулируются. Windows не ставит сообщения таймера в очередь, если в ней уже есть одно сообщение от данного таймера.

Обработка в периоды простоя

До появления многопоточности разработчики программ для Windows использовали периоды простоя (idle) для выполнения фоновых задач, например, разбивки документа на страницы. Теперь обработка во время простоя потеряла былое значение, но ей по-прежнему находится применение. Каркас приложений вызывает виртуальную функцию-член Onldle класса CWinApp, и Вы можете переопределить ее для выполнения фоновых вычислений Onldie вызывается из цикла обработки сообщений MFC-библиотеки, который на самом деле сложнее, чем приведенная выше простая последовательность GetMessage/TramlateMessage/Dispatch-Message. Обычно функция Onldle вызывается после того, как очередь сообщений у приложения опустеет, причем только один раз. Если Вы переопределяете ее, вызывается ваш код, но при отсутствии непрерывного потока сообщений это не происходит постоянно. Onldle в базовом классе обновляет кнопки панели инструментов и индикаторы состояния, а также “чистит” указатели на временные объекты. Имеет смысл переопределять эту функцию, если Вы хотите обновлять состояние элементов пользовательского интерфейса Ну, а то, что она не вызывается в отсутствие сообщений, значения не имеет, ведь пользовательский интерфейс и не должен в этом случае изменяться.

Переопределяя функцию CWinApp::Onldle, не забудьте вызвать Onldle базового класса. Иначе не произойдет ни обновления кнопок на панели инструментов, ни удаления временных объектов.

Onldle вообще не вызывается, если пользователь работает в модальном диалоговом окне или выбирает что-то в меню. При необходимости фоновой обработки модальных диалоговых окон или меню придется написать обработчик сообщения WM_ENTERIDLE, но его надо добавить в класс окна-рамки, а не в класс “вид”. Причина в том, что владельцем диалоговых окон всегда является основное окно-рамка приложения, а не окно представления.