Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timer in a win32 service

Can someone please point me to the easiest way to have a timer in a Win32 service?

I suppose I could create a dummy window for this purpose or have a second thread do tick counts, but what's best? Is there a more elegant way?

Thanks in advance.

like image 637
dennisV Avatar asked Oct 22 '08 00:10

dennisV


5 Answers

You can use Timer Queues (http://msdn.microsoft.com/en-us/library/ms686796.aspx). They don't require an HWND.

like image 136
denis phillips Avatar answered Oct 23 '22 19:10

denis phillips


Instead of using UI timers (even though you can use the NULL window handle as shown by Mr. 1800-INFO) you can use kernel waitable timer objects. See CreateWaitableTimer in the API docs. These can then be waited-on using WaitForSingleObject or WaitForMultipleObjects, etc, which is especially useful if that's already how your service waits for external events.

If it's not clear from that first link, the SetWaitableTimer function can associate a completion routine (user callback) with the timer. Remember to use the ...Ex versions of WaitForMultipleObjects (etc.) so that the thread is in an "alertable" state.

like image 30
Adam Mitz Avatar answered Oct 23 '22 18:10

Adam Mitz


You can send your main thread WM_TIMER messages. The lParam for the message is the address of a callback function, or you can leave it NULL and handle it yourself in your message pump.

In this example, we are sending the timer to the thread message pump, there is no requirement to have a window associated with the timer.

UINT timer;

VOID CALLBACK Timer(HWND hwnd,
    UINT uMsg,
    UINT_PTR idEvent,
    DWORD dwTime
)
{
  KillTimer(0, timer);
}

timer=SetTimer(0, // window handle
    0, // id of the timer message, leave 0 in this case
    10000, // millis
    Timer // callback
  );

// pump messages
while (GetMessage) etc...

The Timer callback will be called by DispatchMessage. This question reminded me of the recent ONT.

like image 4
1800 INFORMATION Avatar answered Oct 23 '22 20:10

1800 INFORMATION


You can use SetTimer to set the timer, then catch the WM_TIMER message in your message loop.

Example:

// Set a timer to expire in 10 seconds

SetTimer(hwnd,IDT_TIMER1, 10000,(TIMERPROC) NULL);

... then in message loop:

switch (wParam)

{ 

    case IDT_TIMER1: 

        // Boom goes the dynamite

You can also decleare a function of type TIMERPROC and have that be called when the timer expires, if you don't want to do the message loop handling.

like image 1
Steve Avatar answered Oct 23 '22 19:10

Steve


In one of your comments you said that "...the service is processing stuff in other threads, I just need to check the status of a few files every second."

Polling is not an optimal way of checking file status, and will adversely affect system performance. While there are (sometimes) problems doing this over networks, you should check out http://msdn.microsoft.com/en-us/library/aa364417(VS.85).aspx or http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx for how to do it and http://blogs.msdn.com/oldnewthing/archive/2006/01/24/516808.aspx for why you should.

like image 1
David L Morris Avatar answered Oct 23 '22 19:10

David L Morris