Blog. Just Blog

Таймер в консольном приложении

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Таймер в консольном приложении
Таймер в консольном приложении

Продолжаем раскрывать возможности консоли. Сегодня это будет выполнение действий через определенные интервалы, то есть, проще говоря, таймеры. В некоторых интернетах всплывает информация, что, мол, таймеры в консольных приложениях не поддерживаются или для этого надо городить какие-то жуткие конструкции типа отдельных потоков с проверкой времени. На самом деле консоль прекрасно работает с функцией SetTimer, только надо ее, как говорится, правильно готовить.

Активация таймеров выполняется при помощи функции SetTimer, но только в качестве окна-владельца таймера надо указывать NULL. Для чистоты эксперимента установим два таймера: один будет отправлять сообщения основному потоку консольного приложения, а второй при срабатывании будет вызывать указанную процедуру. Интервалы срабатывания тоже пусть будут разными.
  1.         ; Установить таймеры
  2.         invoke  SetTimer,NULL,1,500,TimerProc
  3.         mov     [timer1],eax
  4.         invoke  SetTimer,NULL,2,1000,NULL
  5.         mov     [timer2],eax
С первым таймером никаких сложностей нет, задаем процедуру обработки и при получении управления выполняем нужные действия. Тут ничего нового, все в точности, как и в оконных приложениях.
  1. ;-------------------------------------------------
  2. ; Функция обработки таймера
  3. ;-------------------------------------------------
  4. proc TimerProc hWnd:DWORD, nMsg:DWORD, nIDEvent:DWORD, dwTime:DWORD
  5.         pusha
  6.         ...
  7.         ; Выполнить нужные действия по таймеру
  8.         ...
  9.         popa
  10.         ret
  11. endp
Теперь самое интересное - обработка сообщений WM_TIMER в основном потоке приложения. Тут главное понять принцип. В цикле запрашивается очередное сообщение из очереди потока при помощи функции GetMessage, затем оно обрабатывается при помощи функции TranslateMessage и в случае поступления WM_TIMER выполняются те или иные действия. После обработки сообщение удаляется из очереди функцией DispatchMessage.
  1. loc_loop:
  2.         ; Прочитать сообщение из очереди потока
  3.         invoke  GetMessage,msg,NULL,0,0
  4.         or      eax,eax
  5.         je      loc_exit
  6.  
  7.         invoke  TranslateMessage,msg
  8.  
  9.         ; Сообщение от таймера?
  10.         cmp     [msg.message],WM_TIMER
  11.         jne     loc_dispatch
  12.         ; Это нужный нам таймер?
  13.         movzx   eax,word [msg.wParam]
  14.         cmp     eax,[timer2]
  15.         jne     loc_dispatch
  16.  
  17.         ...
  18.         ; Выполнить нужные действия по таймеру
  19.         ...
  20.  
  21. loc_dispatch:
  22.         invoke  DispatchMessage,msg
  23.         jmp     loc_loop
  24.  
  25. loc_exit:
  26.         ; Удалить таймеры
  27.         invoke  KillTimer,NULL,[timer1]
  28.         invoke  KillTimer,NULL,[timer2]
Обратите внимание, что в цикле обработки проверяется идентификатор таймера. Дело в том, что при подобной реализации в очередь сообщений главного потока консольного приложения добавляются сообщения WM_TIMER от всех установленных таймеров. Можете убрать в коде проверку и убедиться в этом. То есть, в принципе, вы можете в цикле основного приложения обрабатывать даже сообщения таймера с указанной процедурой обработчика, но это гарантированно плохая практика, так делать не надо. Если уж ждем пинок от своего таймера, так уж будьте добры обрабатывать именно его. Если уж заявили собственную процедуру обработки какого-то таймера, то вот именно его там и обслуживаем.

При удалении таймеров во время завершения работы программы в параметрах указываем хэндлы таймеров, полученные при их установке.

В приложении пример программы с исходным текстом, которая обрабатывает два таймера в консольном приложении. Выход по клавише Esc.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Console.Timers.Demo.zip (2,382 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 383 | Комментариев: 2

Комментарии

Отзывы посетителей сайта о статье
L-air (08.02.2022 в 09:05):
О, консоль - это круто! Спасибо!
Джо (08.02.2022 в 04:31):
В каком потоке будет выполняться таймер? Вроде как явно в консольном приложении message pump не создается (точнее консольное приложение может работать без message pump).

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2022
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0046 сек.) / Память: 4.75 Mb
Наверх