A Threaded Timer Class
A short while ago I was involved in an MFC project that was doing some simple packet routing. Some packets arrive in fragments, and at times fragments were lost, so there was a need to be able to expire uncompleted packets from the buffer.
It is for this reason that I developed this Timer class. It is an extremely simple class that invokes an operation given by the developer, every certain amount of seconds.
To use this class, you simply have to derive (or multiply inherit) the class that needs this timeout service from Timer. Then, you override the Tick() method and place in the overriden method the code that does whatever needs to be done when timeout occures. In my case this was an expiration of a packet from a buffer.
WHY NOT USE A WINDOWS TIMER? Well it is true that a windows timer ( CWnd::SetTimer() ), which invokes the WM_TIMER message, behaves in a similar way and does not require another thread. Yet, the timer messages get queued with other windows messages and at times, if the user interface is busy, the OnTimer() will not be invoked when it is needed but wait until all the other windows messages get handled. In addition to that, if there is complex processing to be done on timeout, the user interface would be unresponsive, if OnTimer() is used.
So if you need a sure way to get the timeout when you want it, regardless the state of the UI, and dont mind the overhead of another thread, this class is for you.
Well, this class is so simple that it is a waste of time to write about it anymore... Here is the complete implementation so you can see how it works:
// Timer.h: interface for the Timer class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_TIMELIMIT_H__D2107E6A_33E5_11D3_8D14_00E0980636C2__INCLUDED_)
#define AFX_TIMELIMIT_H__D2107E6A_33E5_11D3_8D14_00E0980636C2__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class Timer
{
public:
void StopTicking();
void StartTicking();
Timer();
virtual ~Timer();
int GetTimeout(){return m_msTimeout;}
void SetTimeout(int t){m_msTimeout=t;}
protected:
int m_msTimeout;
virtual void Tick();
private:
HANDLE m_hThreadDone;
bool m_bStop;
static UINT TickerThread(LPVOID pParam);
};
#endif // !defined(AFX_TIMELIMIT_H__D2107E6A_33E5_11D3_8D14_00E0980636C2__INCLUDED_)
// Timer.cpp: implementation of the Timer class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Timer.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Timer::Timer()
{
m_bStop=true;
m_msTimeout=-1;
m_hThreadDone = NULL;
m_hThreadDone = CreateEvent(NULL,FALSE, FALSE, NULL);
ASSERT (m_hThreadDone);
SetEvent(m_hThreadDone);
}
Timer::~Timer()
{
//dont destruct until the thread is done
DWORD ret=WaitForSingleObject(m_hThreadDone,INFINITE);
ASSERT(ret==WAIT_OBJECT_0);
Sleep(500);
}
void Timer::Tick()
{
//Will be overriden by subclass
}
void Timer::StartTicking()
{
if (m_bStop==false)
return; ///ignore, it is already ticking...
m_bStop=false;
ResetEvent(m_hThreadDone);
AfxBeginThread(TickerThread, this);
}
UINT Timer::TickerThread(LPVOID pParam)
{
Timer* me=(Timer*) pParam;
ASSERT (me->m_msTimeout!=-1);
while (!me->m_bStop)
{
Sleep (me->GetTimeout());
me->Tick();
}
SetEvent(me->m_hThreadDone);
return 0;
}
void Timer::StopTicking()
{
if (m_bStop==true)
return; ///ignore, it is not ticking...
m_bStop=true; //ok make it stop
WaitForSingleObject(m_hThreadDone,INFINITE);
//The above ensures that we do not return UNTIL the thread
//has finished. This way we dont allow the user to start multiple
//threads that will execute Tick() at the same time
}
To use it, call the SetTimeout() and then StartTicking() in the subclass. Make sure the subclass has
a void Tick() method which includes the processing to be done at timeout.
The demo project shows a CStatic derivative (CMyStatic) which also derives from Timer and on every tick,
inverts its colors.
Downloads
Download demo project - 37 KbDownload source - 2 Kb

Comments
Stopping the timer from the TICK
Posted by Legacy on 12/02/2003 12:00amOriginally posted by: Patrick Tessier
Hi,
I have been coding on a similar timer before I ended up here to see if someone had the same problem I was confronted too. I have a question for you guys..
What do you thinking (if you leave synchronisation in) would happen if you would call StopTicking from the Tick function (called by the thread) which does a Wait infinite?? The answer is, it will wait infinitely and will never stop waiting until you kill the application because the WAITFORSINGLEOBJECT is called from the thread which causes the thread to wait..
Has anyone been faced with that problem and would someone share with me what they have done?
Regards
Replyproblem!!! no longer generating event
Posted by Legacy on 11/13/2002 12:00amOriginally posted by: aiman
Thanks Tomer Petel and Bongki Kwon
After modify code given Bongki Kwon stop thread in TickerThread() function...
so I can solve it with origianl following partial code...
Bongki Kwon's given code
Reply----------------------------------------------------------
if (WaitForSingleObject(me->m_hEndThread, me->GetTimeout()) == WAIT_TIMEOUT)
{
// No signal received..
me->Tick();
}
else
{
// Signal received to stop the thread.
me->m_bStop = true;
}
-----------------------------------------------------------
TO
while (!me->m_bStop)
{
Sleep (me->GetTimeout());
me->Tick();
}
Thread termination is solved...
Posted by Legacy on 12/23/1999 12:00amOriginally posted by: Bongki Kwon
ReplyThread termination is solved... #modify
Posted by Legacy on 12/23/1999 12:00amOriginally posted by: Bongki Kwon
I miss one line of code at destructor of previous document.
Add next code at destructor
CloseHandle(m_hEndThread) ;
And you may see termination of thread.
ReplyMultimedia timer
Posted by Legacy on 11/26/1999 12:00amOriginally posted by: Christian Demers
You can use a multimedia timer to do the same thing. The multimedia timer is responsible to create the thread and send you an event when period has expired or you pass a callback procedure to receive the notification.
The precision of this timer is better than WM_TIMER and you're able to set the precision you want +- how much milliseconds.
ReplyMemory leak, possible some GDI objects.
Posted by Legacy on 08/11/1999 12:00amOriginally posted by: A. Bjarnason
Your code is very useful and a good idea.
TimeSetEvent(...) performs good as a high resolution
timer but it hijack your machine and you have to reboot
sometimes.
Your class can be derived from CView as example but I noticed memory leak when I used some GDI objects.
InitializeCriticalSection(&Timer::staticVar);
EnterCriticalSection(&Timer::staticVar);
{
// Do something nice within those braces
}
LeaveCriticalSection(&Timer::staticVar);
ReplyI think that you have enter in such section braces when
you want to do some "critical" loop.
Timer Thread made better
Posted by Legacy on 08/10/1999 12:00amOriginally posted by: Gowri Shankar.R
Replyproblem with ~Timer... #2
Posted by Legacy on 08/06/1999 12:00amOriginally posted by: Llew
Reply