A Threaded Timer Class

Environment: VC6 NT/98

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 Kb
Download source - 2 Kb


Comments

  • Lisseur GHD Purple à un défilé de mode à Milan est le meilleur assistant coiffeur

    Posted by qyxvkx743 on 07/16/2013 04:24am

    Le site officiel du GHD a une liste de tous les sites frauduleux connus. Leur outil de vérification de site Web vous permet d'entrer une URL de vérifier pour voir si elle vend de véritables redresseurs. Sites autorisés auront également un badge "ghd approuvé en ligne détaillant" affiché sur leur site, vous devez vérifier qu'il affiche la date et l'heure la plus récente et l'adresse du site à droite pour s'assurer que les signes approuvés sont réels et ont été effectivement délivrés. [url=http://ghdpascherferfr.webgarden.com/]ghd pas cher lisseur[/url] GHD MK4 IV Kiss est la beste ghd tige droite encore été nommé brillante édition rose Kiss sera pour une courte période seulement Tilgiengelig pas aller Glipp audiovisuel votre sjanse sur verktøyet, parfait boucles de terrassement volum - approche de gir et caremic droit tige udisiplinerte ... et son plus sexy été nommé dans le rose de het brillant et comme si cela ne suffisait pas, £ 10 de chaque vente va brystkreft gjennombrudd! [url=http://ghdpascherferfr.blinkweb.com/]ghd lisseur pas cher[/url] Étonnamment GHD (bonne journée de cheveux) avec pratiquement aucune publicité, atteint le statut d'icône en un temps incroyablement court, primé à gauche, à droite et au centre et toutes ces crédits va à un ex-coiffeur pour un salon haut Robert Powles, l'homme qui a pris cette possession.According prix pour le client GHD MK4 styler est considéré comme un bon investissement, il vaut bien le prix. Et les raisons sont assez fantastique et dans l'ensemble ils font le mieux. Une marque GHD mondial superbe est une société britannique, et c'est une entreprise Yorkshire qui croit dur labeur à l'avant-garde des soins capillaires mondiale.

    Reply
  • Quieres obtener el mejor resultado Hairstyler, mejores maneras de aprender a usar mini styler ghd

    Posted by hanmeihm on 05/30/2013 07:40am

    [url=http://www.ghdchheapoutlet.moonfruit.com/]Planchas ghd[/url] Es la celebracin del cumpleaos de la esposa real al da siguiente. Esto se construye con un totalmente entregado a una persona a trav¦s de todo este perodo la derecha hasta que, en la actualidad, la seora comenz a derramar individuos sugerencias anuales m¢s que el desayuno todos los das. Esto requiere algn tiempo, sin embargo, esto modificado. Y as los suda fro comienzan. Qu¦ diablos va a comprar la de la mujer Podra esta funcin en particular como el acabado No tengas miedo! El m¦todo de peluquera esposa apaciguador todos los tiempos completo es accesible bajo costo en una tienda en lnea en su ¢rea. Compr¦ mi esposa algunos alisadores de pelo GHD baratas en la celebracin de su cumpleaos hace una semana y, la verdad, personalmente creo que como recibimos la lotera real. La seora no ha dejado de suceder con respecto a ellos ... Evidentemente, el mejor elemento de peluquera que est¢ realmente utilizada. [url=http://www.planchasespanaghdtop.net/ghdtienda/]GHD Plancha de pelo[/url] Elementos de defensa trmicas podran adquirir f¢cilmente en la red. Abra las planchas ghd, les permiten chisporrotear. Cuando est¢n en el interior de la temperatura m¢xima, parece, la voz y el LED comenzar¢ a parpadear. Se requiere unos veinte segundos en la mejor temperatura se decide por que la temperatura en la zona. As que, para empezar, un componente en el pelo y el manejo del elemento que se use un cepillo o un peine por el uso de asegurarse de que todo el pelo est¢ resuelto. Su pelo ghd Max clip de Diseo probablemente poco a poco cada uno de la manera abajo alrededor acerc¢ndose su raz parada entonces su cabello. Horquilla Cabeza limitado es vital, pero nunca clip de manera limitada, comienza a tirar con su pelo, como resultado de la verdad que esto puede debilitarlo y causar dolor. Es necesario preservar el ejercicio con planchas GHD operacin confiable, hace que todo el pelo es recta normal y ninguna huella se queda dentro de los alisadores de pelo se mantiene a disposicin iros tambin vosotros extended.Once primer adquirir planchas ghd, usted va a encontrarse con dificultades nocountless . [url=http://www.planchaspeloghdes.qsite.dk/]planchas ghd baratas[/url] Ghd Mk4 arcilla Curling hierro es definitivamente maravilloso El termostato de los alisadores de pelo ghd reducir¢ la temperatura progresivamente para que no se corre el riesgo de daar el cabello o secado demasiado. Otra forma de encontrar los ajustes de temperatura adecuadas para su plancha para el cabello es el uso de ellas en una parte de su cabello y observar el efecto que tiene sobre las hebras individuales. Si los hilos parecen demasiado secos y se sienten ¢speras al tacto, puede estar razonablemente seguro de que la temperatura es alta. Si la temperatura que usted ha seleccionado es correcto el cabello se siente suave y sedosa al tacto.

    Reply
  • kategorier:chi fladjern

    Posted by motherdhmm on 05/30/2013 06:42am

    [url=http://www.buy-beatsdrdre.com/]beats by dre[/url] Den alsidighed ghd glattejern giver dig mulighed for at gøre meget mere end bare glatte hår. Den ghd lilla kommer med en intensitet uvillig ghd glattejern omfatter grund ghd glattejern indpakket i et eksklusivt designet rotere måtten med alle nye packaging.With lidt øvelse, kan du skabe volumen og krøller med lethed. [url=http://www.buy-beatsdrdre.com/category/new-beats-dr-dre-headphones]Beats By Dr Dre[/url] Straks efter sammen med din gode hår dage manke styling ædle metaller, erhverve vidunderlige såvel som fysiske egnethed ud over velfærd retsmiddel langs med lægge på det med hensyn til at bruge. Leder af hår vil i alle sandsynlighed ender med at blive avanceret disheveled det samme som bølger kontakt med velkendte mænd og kvinder langs med design og stil plus formatindstillinger. Lige før en person vælger du at efterspørgslen disheveled vises, er du i stand til at oprette din egen personlige personlige bruge højere blot ved besidder en design og storheden brug. Den nøjagtige udformning og elegance draw på vil sandsynligvis fastholde de faktiske private bølger for at kunne du overlegen partier ekstra. Hår på grund af dette vil helt sikkert næsten helt sikkert ofte være innovative sammenholdt med fabelagtig. Du kan konvertere hoved af hår Implementer mens betydeligt, mens alle ønsker når du besidder denne bestemte visse gode hår dage manke hår styling stål. [url=http://www.blog.cheapbeatsbydre.co.nz/monster-headphone]monster beats headphone[/url] Ved hjælp af magi magi ghd glattejern, kan du oprette en stor bølge af hår. Meget velegnet til off bryst hår pige. Brug er meget enkel, først ghd håret varme, hvis man kan operere mere anstrengende omvej first hår ghd håret på genopvarmning, men dette er ikke god temperaturregulering, først med en ghd fladjern hår for klemmer bor, og hår rundt om s-gerne på det, ville det tage at være stor, er du nødt til at cirkel rundt om et par mindre punkter, hvis du ønsker at tilbringe et lille sår på multi-point Best Buy keramik, færre skader ens hår!

    Reply
  • Stopping the timer from the TICK

    Posted by Legacy on 12/02/2003 12:00am

    Originally 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

    Reply
  • problem!!! no longer generating event

    Posted by Legacy on 11/13/2002 12:00am

    Originally 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
    ----------------------------------------------------------
    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();
    }

    Reply
  • Thread termination is solved...

    Posted by Legacy on 12/23/1999 12:00am

    Originally posted by: Bongki Kwon

    This class is very useful.
    
    but, there is a little problem with the destruktor of the Timer-class. When I terminate TimerTst.exe, timer thread(TickerThread()) is not dead. but I found solution of this problem at Gowri Shankar.R's document.

    I add to Gowri Shankar.R's document such as next code.
    ---------------------------------------------------------------------

    add a private variable to the class
    HANDLE m_hEndThread;

    A create event is added to the construcor

    Timer::Timer()
    {
    m_bStop=true;
    m_msTimeout=-1;
    m_hThreadDone = NULL;
    m_hThreadDone = CreateEvent(NULL,FALSE, FALSE, NULL);
    ASSERT (m_hThreadDone);
    SetEvent(m_hThreadDone);
    // code added
    m_hEndThread = NULL;
    m_hEndThread = CreateEvent(NULL,FALSE, FALSE, NULL);
    ASSERT (m_hEndThread);
    SetEvent(m_hEndThread);
    }

    Add this statement to StartTicking() before the AfxBeginThread()
    ResetEvent(m_hEndThread);


    The TickerThread is slightly modified as follows

    UINT Timer::TickerThread(LPVOID pParam)
    {
    Timer* me=(Timer*) pParam;
    ASSERT (me->m_msTimeout!=-1);
    while (!me->m_bStop)
    {
    // Sleep() is changed to this so that a termination of a thread will be received.
    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;
    }
    }
    SetEvent(me->m_hThreadDone);
    return 0;
    }


    SetEvent(m_hEndThread) is added to StopTicking Function to signal thread termination.
    The StopTicking() will be as..

    void Timer::StopTicking()
    {
    if (m_bStop==true)
    return; ///ignore, it is not ticking...

    m_bStop=true; //ok make it stop
    SetEvent(m_hEndThread);
    WaitForSingleObject(m_hThreadDone,INFINITE);
    //The above wait 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
    }
    ---------------------------------------------------------------------

    And modify Timer::~Timer()
    Timer::~Timer()
    {
    //dont destruct until the thread is done
    DWORD ret=WaitForSingleObject(m_hEndThread,INFINITE);
    ASSERT(ret==WAIT_OBJECT_0);
    Sleep(500);
    }

    When your application is terminated, timer thread is died simultaneously.

    Reply
  • Thread termination is solved... #modify

    Posted by Legacy on 12/23/1999 12:00am

    Originally 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.

    Reply
  • Multimedia timer

    Posted by Legacy on 11/26/1999 12:00am

    Originally 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.

    Reply
  • Memory leak, possible some GDI objects.

    Posted by Legacy on 08/11/1999 12:00am

    Originally 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);


    I think that you have enter in such section braces when
    you want to do some "critical" loop.

    Reply
  • Timer Thread made better

    Posted by Legacy on 08/10/1999 12:00am

    Originally posted by: Gowri Shankar.R

    Good work.
    
    The Class is very useful and handy.
    A small problem is if the time is set to some minutes
    and if the thread enters into sleep state you cannot
    terminate the program immediately and so u
    have to wait some time for the thread to come out of sleep
    for the application to terminate.
    so a few changes can be made to the code so that the application
    terminates immediately.


    add a private variable to the class
    HANDLE m_hEndThread;

    A create event is added to the construcor

    Timer::Timer()
    {
    m_bStop=true;
    m_msTimeout=-1;
    m_hThreadDone = NULL;
    m_hThreadDone = CreateEvent(NULL,FALSE, FALSE, NULL);
    ASSERT (m_hThreadDone);
    SetEvent(m_hThreadDone);
    // code added
    m_hEndThread = NULL;
    m_hEndThread = CreateEvent(NULL,FALSE, FALSE, NULL);
    ASSERT (m_hEndThread);
    SetEvent(m_hEndThread);
    }

    Add this statement to StartTicking() before the AfxBeginThread()
    ResetEvent(m_hEndThread);


    The TickerThread is slightly modified as follows

    UINT Timer::TickerThread(LPVOID pParam)
    {
    Timer* me=(Timer*) pParam;
    ASSERT (me->m_msTimeout!=-1);
    while (!me->m_bStop)
    {
    // Sleep() is changed to this so that a termination of a thread will be received.
    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;
    }
    }
    SetEvent(me->m_hThreadDone);
    return 0;
    }


    SetEvent(m_hEndThread) is added to StopTicking Function to signal thread termination.
    The StopTicking() will be as..

    void Timer::StopTicking()
    {
    if (m_bStop==true)
    return; ///ignore, it is not ticking...

    m_bStop=true; //ok make it stop
    SetEvent(m_hEndThread);
    WaitForSingleObject(m_hThreadDone,INFINITE);
    //The above wait 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
    }

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 10, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild". This loop of continuous delivery and continuous feedback is …

  • Live Event Date: September 17, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Another day, another end-of-support deadline. You've heard enough about the hazards of not migrating to Windows Server 2008 or 2012. What you may not know is that there's plenty in it for you and your business, like increased automation and performance, time-saving technical features, and a lower total cost of ownership. Check out this upcoming eSeminar and join Rich Holmes, Pomeroy's practice director of virtualization, as he discusses the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds