Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > SetTimer. механизм срабатывания callback


Автор: Lexicss 19.2.2008, 16:13
UINT SetTimer(
    HWND hWnd,    // handle of window for timer messages
    UINT nIDEvent,    // timer identifier
    UINT uElapse,    // time-out value
    TIMERPROC lpTimerFunc    // address of timer procedure
   );
Функция SetTimer. Вызвав её с нулевыми параметрами дискриптора окна и идентифекатора, но с указанием адреса функции - выполняет функцию в потоке, который вызвал SetTimer, через указанный uElapse промежуток времени. 
Вопрос: Как ведёт себя вызваший поток, когда срабатывает таймер? Он ведь в это время может выполнять какие-то инструкции, а необходимо непременно выполнить callback function...  Вообщем, как осуществляется выполнение callback-функции вызванной таймером?
Не могу пока  найти никакой информации по этому.

Автор: Rennigth 19.2.2008, 16:19
Lexicss, 
Цитата

lpTimerFunc
[in] Pointer to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc. If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message's MSG structure contains the value of the hWnd parameter. 

Автор: Alexeis 19.2.2008, 16:20
Цитата

When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.

  Сообщение WM_TIMER по любому попадет в очередь сообщений потока и дефолтный обработчик должен вывать калбэк, если очереди сообщений нет, то фиг вам будет, а не калбэк  smile 

Автор: Lexicss 19.2.2008, 16:52
Rennigth, ну у меня ж lpTimerFunc = не NULL. 

Alexeis, 
Как я этот механизм понимаю:
Значит любой поток имеет дефолтный обработчик. И когда в очередь сообщений текущего потока попадает WM_TIMER, то этот дефолтный обработчик и вызывает callback-функцию.

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


Автор: Alexeis 19.2.2008, 17:00
Цитата(Lexicss @  19.2.2008,  15:52 Найти цитируемый пост)
Но я всё равно и не понял, как прерывается работа потока? Например, вызвал я SetTimer в главном потоке. Сработал таймер, обработчик спаймал WM_TIMER и тут же принялся выполнять колбэк-функцию, а когда выполнил, то вернулся снова к своим делам? Так что ли?

  Угу.

Автор: Rennigth 19.2.2008, 17:02
Цитата(Lexicss @  19.2.2008,  16:52 Найти цитируемый пост)
Но я всё равно и не понял, как прерывается работа потока?

Если есть в потоке очередь сообщений, и поток в данный момент не занят чем либо еще то рано или поздно он поймает WM_TIMER и выполнит твою lpTimerFunc. Выролнение какого-то кода не прервется, если конечно не выполнять всяких Application.ProcessMessages.

Автор: Lexicss 19.2.2008, 17:03
Alexeis, 
Где-то я такое слышал что нельзя поток просто так взять и прерывать в случайный момент времени.

Добавлено через 7 минут и 14 секунд
Rennigth, 
Тогда смысл такой:
поток перебирает свою очередь и обрабатывает один за другим свои сообщения. т.о. и обрабатывает колбэк-функцию, когда добирается до WM_TIMER.

Т.е. никакого механизма с тревожным ожиданием потока здесь нет?

Автор: Alexeis 19.2.2008, 17:13
Получается, что если назначено окно, то вызывает API функция DefWindowProc если нет окна, то DispatchMessage

Автор: Lexicss 19.2.2008, 17:32
Есть ещё такое понятие как поступление APC-запроса в очеред с указанием адреса функции и параметра. 
В SetTimer и есть этот механизм?
Или здесь совсем нето. wm_timer сообщение в параметрах хранит адрес функции для обработчика?

Добавлено через 2 минуты и 49 секунд
Т.е. поток при срабатывании таймера не вводится в режим тревожного ожидания?
(хочу просто чётко с этим разобраться)

Автор: MetalFan 19.2.2008, 17:48
Цитата(Lexicss @  19.2.2008,  17:32 Найти цитируемый пост)
Есть ещё такое понятие как поступление APC-запроса в очеред с указанием адреса функции и параметра. 
В SetTimer и есть этот механизм?

нет, этот механизм в таймерах ожидания и в очередях таймеров применяться afaik (Waitable Timer, Timer Queue)

Автор: Rennigth 19.2.2008, 17:54
Цитата(Lexicss @  19.2.2008,  17:32 Найти цитируемый пост)
Есть ещё такое понятие как поступление APC-запроса в очеред с указанием адреса функции и параметра. 
В SetTimer и есть этот механизм?

Нет.

Цитата(Lexicss @  19.2.2008,  17:32 Найти цитируемый пост)
Или здесь совсем нето. wm_timer сообщение в параметрах хранит адрес функции для обработчика?

Да.


Цитата(Lexicss @  19.2.2008,  17:32 Найти цитируемый пост)
Т.е. поток при срабатывании таймера не вводится в режим тревожного ожидания?
(хочу просто чётко с этим разобраться) 

Если честно незнаю что ты имеешь ввиду под понятием "тревожного ожидания" smile

Вообщем юзай SetTimer/KillTimer и не тревожся. Он не очень точный конечно, есть другие, более точные, например мультимедийный таймер, вот они уже работаеют по всяким прерываниям и т.д.(не особо знаю механизм), и тогда уже могут возникать проблемы и может понадобится подобие синхронизации...

Автор: Lexicss 19.2.2008, 18:04
MetalFan, как это можно проверить на примере?

Автор: MetalFan 19.2.2008, 19:07
Lexicss, что проверить? msdn уже нет доверия? )

Автор: bems 19.2.2008, 19:16
Цитата(Alexeis @  19.2.2008,  17:13 Найти цитируемый пост)
Получается, что если назначено окно, то вызывает API функция DefWindowProc если нет окна, то DispatchMessage 
в любом случае _нужно_ вызывать DispatchMessage. А она уже передаст или в калбек или в процедуоу окна. Как в подпрограмму

Автор: MetalFan 19.2.2008, 22:06
Цитата(bems @  19.2.2008,  19:16 Найти цитируемый пост)
в любом случае _нужно_ вызывать DispatchMessage

сначало необходимо создать очередь сообщений. вызвав GetMessage (PeekMessage)

Автор: Lexicss 20.2.2008, 08:53
Цитата(MetalFan @  19.2.2008,  19:07 Найти цитируемый пост)
Lexicss, что проверить? msdn уже нет доверия? )

Типа того smile . Хочу всё же на практике в этом убедиться.

Автор: MetalFan 20.2.2008, 09:33
Цитата(Lexicss @  20.2.2008,  08:53 Найти цитируемый пост)
Хочу всё же на практике в этом убедиться. 

ну так убеждайся. создай допустим таймер ожидания (CreateWaitableTimer, SetWaitableTimer). переведи поток в "тревожное состояние" и убедись)

Автор: Lexicss 20.2.2008, 15:23
C SetTimer разобрался и проверил. Всё действительно так и есть: Когда срабатывает таймер, генерируется сообщение WM_TIMER с параметрами идентификатора этого таймера и адресом функции. Когда обработчик текущего потока обнаруживает в очереди это сообщение, то вызывает callback-функцию. Если в этом потоке присутсвуют свои обработчики сообщений, не имеющие ограничений, то они тоже срабатывают. Вообщем, вопрос решён. 
Спасибо большое всем за разъяснение.

P.S.: С SetWaitableTimer щас эксперементирую. Но это уже будет отдельная тема(если опять во что-нибудь уткнусь).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)