Представим себе такую ситуацию.
Имеется Windows-приложение, оконная процедура обработки Windows-событий (не важно, с использованием MFC или нет). И в некоторой точке этой процедуры требуется реализовать следующую логику. Выждать тайм-аут (скажем, минуту), после чего выполнить следующее действие.
Как это красиве сделать?
Тупо выждать Sleep (60000) совсем некрасиво. Так как в этом случае приложение на эту минуту совсем "умрет" - не будет реагировать ни на какие другие события.
То есть, идеально красиво было бы здесь выйти из процедцуры-обработчика событий, а через требуемое время получить какое-то определенное Windows-событие и тут уже продолжить свои дальнейшие действия.
Можно, конечно через SetTimer (... 60000). Т.е. взводим таймер, тут же выходим из обработчика и спокойно ждем, когда таймер опять же вызовет процедцру-обработчик. Там этот таймер убиватся (KillTimer) и делается требуемое действие.
Вроде бы уже красивее, но если такие ситуации в дальнейшем будет возникать постоянно, то хороши ли это будут такие частые установки/убивания таймера? Как это (частые вызовы SetTimer/KillTimer) вообще влияет на ресурсы/производительность Windows?
Опять же MSDN пишет, что таймеры в Windows - ограниченные ресурсы. И, в принципе, вызов SetTimer может обернуться неудачей. Т.е. еще вот такой "подводный камень":
Timers are a limited global resource; therefore it is important that an application check the value returned by the SetTimer member function to verify that a timer is actually available.
Может быть, есть еще какие-то способы?
Заранее спасибо.
Выдержать "паузу" в приложении.
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
C таймером самое простое, и то что там пишут - ниразу не нарывался на проблему нехватки таймеров.
Но если тебе надо сделать все так уж правильно, то имеет смысл закрутить цикл обработки сообщений в этом месте. Так делают модальные диалоги. В этом случае ничего не "умрет" все события так же будут поступать в оконные обработчики. Разве что в основной цикл обратотки сообщений не будут они проходить, возможно в MFC могут возникнуть накладки.
Но с циклом тоже проблема, стандартная функция GetMessage не подразумевает таймаутов, т.е. если не придет ниодного сообщения так и будет висеть. Так что придется применять что-нить вроде MsgWaitForMultipleObjects.
Но если тебе надо сделать все так уж правильно, то имеет смысл закрутить цикл обработки сообщений в этом месте. Так делают модальные диалоги. В этом случае ничего не "умрет" все события так же будут поступать в оконные обработчики. Разве что в основной цикл обратотки сообщений не будут они проходить, возможно в MFC могут возникнуть накладки.
Но с циклом тоже проблема, стандартная функция GetMessage не подразумевает таймаутов, т.е. если не придет ниодного сообщения так и будет висеть. Так что придется применять что-нить вроде MsgWaitForMultipleObjects.
Здесь само собой напрашивается использование потоков и объектов синхронизации, типа Event. А в функции WaitForSingleObject() задать в качестве параметра время ожидания. Тогда не нужен будет никакой цикл. Да и завершить поток при необходимости можно будет досрочно, если принудительно изменить состояние объекта Event.
-
- Сообщения: 1213
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
А что, модальный диалог с прогресс-баром показать не судьба?BBB писал(а):Представим себе такую ситуацию.
Имеется Windows-приложение, оконная процедура обработки Windows-событий (не важно, с использованием MFC или нет). И в некоторой точке этой процедуры требуется реализовать следующую логику. Выждать тайм-аут (скажем, минуту), после чего выполнить следующее действие.
2B OR NOT(2B) = FF
Если в другом потоке то да, а сли хочется сделать паузу в основном потоке, то WaitSingleObject так же остановит поток как и Sleep. Все сильно зависит от того какие глабальные задачи стоят и для чего нужна такая пауза.WinMain писал(а):Здесь само собой напрашивается использование потоков и объектов синхронизации, типа Event. А в функции WaitForSingleObject() задать в качестве параметра время ожидания. Тогда не нужен будет никакой цикл. Да и завершить поток при необходимости можно будет досрочно, если принудительно изменить состояние объекта Event.
То есть?Absurd писал(а):А что, модальный диалог с прогресс-баром показать не судьба?
Есть ещё в системе так называемый Waitable Timer. Соответственно, функции для него CreateWaitableTimer() и SetWaitableTimer().
По-моему, это как раз то, что тебе нужно.
По-моему, это как раз то, что тебе нужно.
-
- Сообщения: 1213
- Зарегистрирован: 26 фев 2004, 13:24
- Откуда: Pietari, Venäjä
- Контактная информация:
В прямом смысле: пока на экраме модальный диалог, приложение заблокировано до тех пор пока оно (т.е модальное окно) не закроется. Следовательно, надо не размещать на модальном диалоге конпки "Закрыть" и рисовать прогресс-бар чтобы юзверь не думал что программа повисла.BBB писал(а):То есть?
2B OR NOT(2B) = FF
Да это вообще предполагается программа, которая без участия пользователя "в автономе" должна работатьAbsurd писал(а):В прямом смысле: пока на экраме модальный диалог, приложение заблокировано до тех пор пока оно (т.е модальное окно) не закроется. Следовательно, надо не размещать на модальном диалоге конпки "Закрыть" и рисовать прогресс-бар чтобы юзверь не думал что программа повисла.
Правильно ли я понимаю, что последовательность действий примерно такая:WinMain писал(а):Есть ещё в системе так называемый Waitable Timer. Соответственно, функции для него CreateWaitableTimer() и SetWaitableTimer().
По-моему, это как раз то, что тебе нужно.
hTimer = CreateWaitableTimer (NULL, TRUE, NULL); // или 3-й п-ер какое-нибудь имя
Далее, в момент начала паузы:
SetWaitableTimer (hTimer, <интервал_паузы>, 0,
MyCompletionRoutine, // completion routine
&MyArgToCompletionRoutine, // completion routine parameter
0);
По истечении указанного промежутка вызовется MyCompletionRoutine.
А отменить таймер (если до истечения указанного промежутка выясниться, что он уже не актуален):
CancelWaitableTimer (hTimer);
Далее по необходимости возможны повторные вызовы SetWaitableTimer.
Так?