Click here to Skip to main content
13,248,766 members (51,241 online)
Click here to Skip to main content
Add your own
alternative version


31 bookmarked
Posted 26 Jan 2004

Threads And Timers

, 26 Jan 2004
Rate this:
Please Sign up or sign in to vote.
Adding a WM_TIMER message to CWinThreads.


In this project and in the source files, there is a base class to CWinThread class that will provide you with WM_TIMER messages to your threads. Since WM_TIMER messages are reserved for window objects only, this is a bit tricky to perform. I did this because I was in need of threads that could react to timers but I had lots of threads (100's) to manage and they all read there configuration from the database and set timers based on that configuration. Some threads had 1 timer and other threads had 100's of timers. I needed a way to manage all these timers and events.

Using the code

This class is derived from the standard MFC CWinThread class. m_autoremove will remove all the timers outstanding if you don't. You can turn it off by setting the m_autoremove to false. There are 2 methods AddTimer() and RemoveTimer(). Simple!

// WinTimerThread.h
class CWinTimerThread : public CWinThread

        bool    m_autoremove;
        UINT_PTR AddTimer(UINT uElapse);
        BOOL RemoveTimer(UINT_PTR idEvent);

// WinTimerThread.cpp
// Static declarations
static CMapPtrToPtr g_MapTimerID_TO_CWinThreadPtr;

static void CALLBACK TimerProc(
    HWND hwnd,         // handle to window
    UINT uMsg,         // WM_TIMER message
    UINT_PTR idEvent,  // timer identifier
    DWORD dwTime       // current system time 
    CWinThread* pThread;

    if (g_MapTimerID_TO_CWinThreadPtr.Lookup((void *) idEvent, (void*&) pThread))
        pThread->PostThreadMessage(WM_TIMER, idEvent, dwTime);
// Class 

    m_autoremove = true;

    // check if autoremove is activated
    if (!m_autoremove)
    // declare local variables
    POSITION pos;
    UINT_PTR idEvent;
    CWinThread* pThread;

    //get the starting point in the list of timer events
    pos = g_MapTimerID_TO_CWinThreadPtr.GetStartPosition();
    //loop while there are list items
    while (pos)
        // get timer event entry
            (void *&) idEvent, (void*&) pThread);
        // check if the idevent is refering to this object
        if (pThread == this)

UINT_PTR CWinTimerThread::AddTimer(UINT uElapse)
    UINT_PTR idEvent;

    idEvent = ::SetTimer(NULL, NULL, uElapse, (TIMERPROC) TimerProc);
    g_MapTimerID_TO_CWinThreadPtr.SetAt((void *) idEvent, this);
    return idEvent;
BOOL CWinTimerThread::RemoveTimer(UINT_PTR idEvent)
    ::KillTimer(NULL, idEvent);
    return g_MapTimerID_TO_CWinThreadPtr.RemoveKey((void *) idEvent);

Below is how to use the new CWinTimerThread.

// MyThread.h
#include "WinTimerThread.h"

#if !defined(MYTHREAD_H)
#define MYTHREAD_H
#pragma once

class CMyThread : public CWinTimerThread

        virtual BOOL InitInstance();
        virtual int ExitInstance();

        void SetLogWindow(CWnd* pWnd);

        CWnd* m_pLogWnd;
        void LogMessage(CString& logmsg);
        void OnTimer(WPARAM idEvent, LPARAM dwTime);

#endif // MYTHREAD_H

Notice that all you have to do is call AddTimer() anywhere in the thread and specify the amount of milliseconds, and you're done. The clean up is done for you so you don't even have to worry about it.

// MyThread.cpp
#include "stdafx.h"
#include "MyThread.h"

#ifdef _DEBUG
#define new DEBUG_NEW



BEGIN_MESSAGE_MAP(CMyThread, CWinTimerThread)

BOOL CMyThread::InitInstance()
    return TRUE;

Points of Interest

Posting the WM_TIMER message to the thread should be safe since the numeric value is 0x113, well below WM_USER = 0x400. This is very compatible to the original SetTimer(), KillTimer() and OnTimer(idEvent, dwTime).

Also note that the message to the thread is ON_THREAD_MESSAGE() not the ON_MESSAGE() macro.


Version 1.0


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

David A. Jones
Web Developer
Canada Canada
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralExcellent article; one small quibble on thread safety Pin
Hal Berman29-May-08 7:06
memberHal Berman29-May-08 7:06 
Generalfrequency of running process Pin
mehmetned17-Jul-06 23:53
membermehmetned17-Jul-06 23:53 
GeneralRe: frequency of running process Pin
David A. Jones18-Jul-06 5:23
memberDavid A. Jones18-Jul-06 5:23 
GeneralCWinThread and SetTimer Pin
kumar_subrahmanya7-Jul-06 2:58
memberkumar_subrahmanya7-Jul-06 2:58 
GeneralRe: CWinThread and SetTimer [modified] Pin
David A. Jones12-Jul-06 6:20
memberDavid A. Jones12-Jul-06 6:20 
Yes there are many issues with what you suggest. Especially if your using threads. You will find that the WM_TIMER message will get dispatched ok if the main UI thread doesn't get locked on other events. Once that UI gets locked on an event your WM_TIMER message will not get dispatched to the other threads. Using CWinTimerThread object this doesn't not happen. The timer dispatch happens inside the windows kernel because it's a call back. A very subtle difference.

Another issue is object ownership. In some cases that I found working with threads and having threads spawn threads is that WM_TIMER messages where only getting dispatched to direct children of the UI thread but if a child thread spawned another thread the WM_TIMER message would sometimes not get sent to these child threads. I would consider it a bug in windows but they have this whole "object ownership" paper that I know understand. Handles and other OS objects can not be shared between threads.

Anyways, if it was as easy as you suggest I wouldn't have written my article in the first place.

My recommendation is to use my object class and enjoy the benefits of it. Smile | :)



-- modified at 11:23 Wednesday 12th July, 2006
Generalerror while creating class derived from CWinThread Pin
VC++error11-Jul-05 11:47
sussVC++error11-Jul-05 11:47 
GeneralOnTimer() Pin
medlar12-Jun-05 23:27
membermedlar12-Jun-05 23:27 
GeneralChanging the AddTimer Pin
Tom Wright10-Mar-05 11:10
memberTom Wright10-Mar-05 11:10 
GeneralRe: Changing the AddTimer Pin
Tom Wright10-Mar-05 12:00
memberTom Wright10-Mar-05 12:00 
GeneralRequired in Visual Studio 6.0 Env. Pin
sudiptam29-Sep-04 2:27
membersudiptam29-Sep-04 2:27 
GeneralRe: Required in Visual Studio 6.0 Env. Pin
David A. Jones1-Oct-04 16:12
memberDavid A. Jones1-Oct-04 16:12 
QuestionIs it really possible to create 100's of Timers? Pin
Persia26-Feb-04 3:17
memberPersia26-Feb-04 3:17 
AnswerRe: Is it really possible to create 100's of Timers? Pin
David A. Jones26-Feb-04 5:43
memberDavid A. Jones26-Feb-04 5:43 
Generalversion 7.10 Pin
Gopal Krishna15-Apr-04 4:46
sussGopal Krishna15-Apr-04 4:46 
GeneralRe: version 7.10 Pin
David A. Jones16-Apr-04 3:53
memberDavid A. Jones16-Apr-04 3:53 
AnswerRe: Is it really possible to create 100's of Timers? Pin
David A. Jones1-Oct-04 16:09
memberDavid A. Jones1-Oct-04 16:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171114.1 | Last Updated 27 Jan 2004
Article Copyright 2004 by David A. Jones
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid