Timer in a win32 service - c++

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.

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

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.

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.

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.

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.

Are you just trying to "wake up" every now and then to do some work? You can always use Sleep().
Additionally, I typically have a thread that is in a while(1 == 1) loop with a sleep inside. There I can check for the shutdown request and other misc housekeeping. You could use that system to tickle an event or mutex for the worker thread in the app.

Related

Will CDialog:SetTimer() lock up a thread if KillTimer() is never called?

BOOL CMemeDlg::PreTranslateMessage(MSG* pMsg)
{
CString csMessage;
if (pMsg->message == WM_KEYDOWN)
{
if (pMsg->wParam == VK_HOME)
{
KillTimer(TIMER_ID_FIELD);
SetTimer(TIMER_ID_FIELD, 500, NULL);
return true;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
In this code snippit will the timer lock up a thread, assuming that there's no other KillTimer somewhere else in the code flow?
If there is no KillTimer() at all, SetTimer() will simply reset an existing timer if it already exists. So you are not going to be over-burdening the thread with multiple timers.
The WM_TIMER message is a synthesized message. When message retrieval is performed via (Get|Peek)Message() and there are no actual messages available in the queue (or if message retrieval is filtering for WM_(SYS)TIMER specifically), then the timer is checked and an actual WM_TIMER message is generated in the message queue only if the timer has elapsed.
So, as long as you are processing those WM_TIMER messages properly, you won't over-burden your thread with unnecessary timer processing.
Just be careful that you don't perform a lot of message retrievals that ignore WM_TIMER, otherwise you can fill up your message queue (see Even though mouse-move, paint, and timer messages are generated on demand, it’s still possible for one to end up in your queue and Why is my message queue full of WM_TIMER messages?.
No. Just every 500msec the WM_TIMER message will be sent.
If the handler is lightweight you will not even see any activity in the task manager.

C++ Timer, Thread, periodic calls

I have issue with thread-safe callbacks.
void draw_something() { /* draws something */ }
And the question is, how to call draw_something in main application thread every specify amount of time irrespective of other code(so it would act like C# Timer and fire function in main thread)? Earlier I was using CreateWindow to create(in main thread) auxiliary window which handles messages from SendMessage(which was sent from another timer-thread):
void MainThreadFunction(){
CreateThread(0, NULL, GoProc, NULL, NULL, NULL);
}
DWORD WINAPI GoProc(LPVOID lpParam){
while(1){
SendMessage(auxiliary_window_hWnd, ADDINATIONAL_MESSAGE, 0, 0);
Sleep(30);
}
return 0;
}
So window's MessageQueue deals safethread calls, but I don't think if it's very efficient and elegant way to do it. I know there is better way(maybe boost?) but I don't know it.
You can use the Windows SetTimer call to get a periodic WM_TIMER message and skip the second thread altogether.
You can't just magically "interrupt" the running thread and "inject" your own code, not in the userspace anyway.
The solution you already have, which is essentially a form of message passing, is fine if you don't have particularly strict temporal requirements.
If time is important to you, i.e. you have to guarantee certain latency between event (passage of time in your case) and processing of that event, you'll have to do the processing in the thread that "detected" the event or maintain a pool of worker threads ready to wake-up and do the processing on moment's notice. But I'm guessing draw_something() must be done on UI thread, so this solution is probably out.

How to Use Timer in MFC Dialog based Application?

I am developing MFC Dialog based application in Visual Studio 2008. I want to use timer that start on start of the application and continue to run and calls a function that performs my task? How can I do this?
Thanks
Just use SetTimer method, and pass two arguments: Timer ID (any number), and the timeout in milliseconds. Then write up OnTimer implementation, and an entry ON_WM_TIMER inside BEGIN_MESSAGE_MAP...END_MESSAGE_MAP.
CWnd::SetTimer takes 3 parameters, but only 2 are required. Pass third argument as NULL.
CWnd::OnTimer
_AFXWIN_INLINE UINT_PTR CWnd::SetTimer(UINT_PTR nIDEvent, UINT nElapse,
void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD))
You may want to do something like
UINT_PTR myTimer = SetTimer (1, 1000, null); // one event every 1000 ms = 1 s
and react to the ON_TIMER event in your window's event handler:
void CMyView::OnTimer (UINT_PTR nIdEvent)
{
if (nIdEvent == 1)
// handle timer event
}
Alternatively you can pass a pointer to a function handling the timer events. Keeping the handle to the timer allows you to turn it off using KillTimer() in case you have to.
If you want to get the basic idea of using Timers, kindly have a look at this link and go through the step by step procedure on working with timers. After this, you should be able to use timers easily in your application whenever you want.
Link: http://www.functionx.com/visualc/controls/timer.htm
Hope this helps.
Cheers.

How do I SendMessage() to a window created on another thread?

I have a situation where I want to SendMessage to a window that was created on another thread than the one that is calling SendMessage.
The default behaviour seems to be block forever and not work.
So I changed the call to PostMessage, which didn't block the sending thread, but the message never appears to arrive at the intended window.
So how do I SendMessage to a window created on a separate thread, or is this impossible?
The PostThreadMessage function posts a message to the message queue of the specified thread. you can specified Identifier of the thread to which the message is to be posted. is that you want?
What is the thread that owns the target window doing? It needs to be pumping messages in order to be able to receive messages that are either sent or posted to it. Typically this is done by having a GetMessage/TranslateMessage/DispatchMessage loop. If the thread is doing something else - such as blocking waiting for an event or mutex or IO to complete, or is busy in some other loop carrying out a calculation, it won't receive messages: SendMessage to the thread will block, and PostMessage will post but not get delivered.
If that target thread needs to both manage events or similar, and it also owns a window, you may need to use MsgWaitForMultipleObjects in that thread's message loop.
You are running into a deadlock. An example, if you SendMessage to another thread, then the windowProc in that thread does SendMessage back to your window, they will lock waiting each other forever.
You need to either fix PostMessage (it does deliver messages, there's just error in your code somewhere), or be very careful about who calls who and when.
To protect against threads that are busy or hung, there is SendMessageTimeout.
Each control you create belongs to the thread that created it, which means that the WndProc for that control will be running in the thread that created the control. You send messages with SendMessage and PostMessage freely to any control.
The issue with CWnd::PostMessage and CWnd::SendMessage is the same. The message is being pushed out, and not being received by anything. SendMessage is blocking by design; it's job is to block the thread until the message is received.
MSDN says this about SendMessage:
"The SendMessage function calls the window procedure for the specified
window and does not return until the window procedure has processed
the message."
It is possible to send a message to window on another thread using CWnd::PostThreadMessage or winapi PostMessage. When you create the window you can use GetSafeHwnd() to get the handle or you can use a thread ID when the thread is created.

How can I show a modeless dialog and display information in it immediately?

I want to show a modeless dialog on the screen and display some information in it.
However if I use it the following way, it has some problems:
function()
{
showdialog(XXX).
//heavy work.
update the dialog..
//heavy work.
update the dialog...
}
It seems the dialog displayed, but it does not draw any information in it. It only draw all information when the function is over.
How can I modify the modeless dialog so it will display the information immediately?
There are a few things you can do.
(1) You could post the dialog a message from inside the CDialog::OnInitDialog method and then handle the long function in the message handler of that posted message. That way the dialog will first be displayed and then later the long function will get run.
(2) The second option is to make sure the message loop gets some processing time. So if your long function is some sort of loop just add the occasional call to the ProcessMessages to make sure the message queue is kept empty:
void ProcessMessages()
{
MSG msg;
CWinApp* pApp = AfxGetApp();
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
pApp->PumpMessage();
}
}
Edit: It certainly is possible to use threads is such a situation, but doing so is not always without risk and complexity.
Using threads with a GUI means having to deal with multiple message queues which then means using API's like PostThreadMessage and that introduces a new set of issues to be wary of.
For an example of one such issue refer to this link:
http://msdn.microsoft.com/en-us/library/ms644946(VS.85).aspx
where is says:
Messages sent by PostThreadMessage are
not associated with a window. As a
general rule, messages that are not
associated with a window cannot be
dispatched by the DispatchMessage
function. Therefore, if the recipient
thread is in a modal loop (as used by
MessageBox or DialogBox), the
messages will be lost. To intercept
thread messages while in a modal
loop, use a thread-specific hook.
I use the process message approach in the Zeus IDE and it works very well at making sure the GUI remains responsive to the user. It is also has the advantage of being very easy to implement.
In OnInitDialog, start a worker thread to perform the computations. Post a user message from the worker thread to update the dialog.
This is superior to the ProcessMessages implementation for several reasons:
The code for doing the calculations can be separated out of the UI code, where it does not belong.
The UI remains responsive while the actual calculations are being performed. ProcessMessages allows multiple UI updates during the single calculation function, but the UI will still be blocked during the actual calculations.
Dialog code:
#define WM_NEW_COUNT (WM_USER + 0x101)
BEGIN_MESSAGE_MAP()
ON_MESSAGE(WM_NEW_COUNT, OnNewCount)
END_MESSAGE_MAP()
BOOL CMyDialog::OnInitDialog()
{
CWinThread* pThread = AfxBeginThread(MyCountFunc, this->GetSafeHwnd());
return TRUE;
}
LRESULT CMyDialog::OnNewCount(WPARAM wParam, LPARAM)
{
int newCount = (int)wParam;
// m_count is DDX member, e.g. for label
m_count = newCount;
UpdateData(FALSE);
return 0;
}
The worker thread:
UINT MyCountFunc(LPVOID lParam)
{
HWND hDialogWnd = (HWND)lParam;
for (int i=0; i < 100; ++i)
{
PostMessage(hDialogWnd, WM_NEW_COUNT, i, NULL);
}
}
As a rule of thumb, heavy computations should never be placed in the GUI thread. Since it is a modeless dialog, the dialog will not own the message loop. The ProcessMessage() solution will work, but is IMO not the right way. My suggestion is:
1) Spawn a new thread in OnInitDialog()
2) Have the separate thread post messages to the dialog when something interesting happens. One of these interesting things is that the work is done.
Note, however, that this will mean that you need to perform proper synchronization.
Don't try to do your heavy work all at once. Have the dialog post itself a message in the WM_APP range in OnInitDialog. The WM_APP handler can do part of the heavy work, then do another PostMessage and return. In this way, you allow the message pump to process window messages in between your chunks of processing.