Re: Thread and Timer

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



That's right. That's what you would expect in a thread which has no message pump, or for
which you blocked the message pump.

First, callback timers are about the most useless entities in all of Windows. Try to
avoid them because they give no value, and only add gratuitous complexity to the problem,
such as the pointless global variables you have. These would not be needed had the timer
callback been designed correctly, which it wasn't.

The presence of global variables should already be a sign that the approach is wrong.
There are very limited number of APIs for which these make sense at all, and every one of
those APIs represents a faulty design on the part of Microsoft.


On Wed, 12 Mar 2008 00:55:52 -0700 (PDT), Stefano <posting@xxxxxxxxxx> wrote:

Hi,
I'd like to use a timer inside a thread (CWinThread derived class).
If I use the CALLBACK procedure I get the timer, if I don't use the
CALLBACK and handle in OnTimer I never get the message.
Here is the code:

// WatchDog.cpp : implementation file
//

#include "stdafx.h"
#include "xcrashreport.h"
#include "WatchDog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CString g_sFileName;
HWND g_hWnd;
UINT g_iMessage;
UINT g_iTimer;
UINT g_iTimerTimeout;

/////////////////////////////////////////////////////////////////////////////
// CWatchDog

void CALLBACK OnTimerProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_TIMER message
UINT_PTR idEvent, // timer identifier
DWORD dwTime // current system time
)
{ // OnTimerProc

if (idEvent == g_iTimer)
{
PostMessage(g_hWnd, g_iMessage, WPARAM (0), LPARAM (0));


KillTimer( NULL, g_iTimer );
AfxEndThread( 0, false );

}

} // OnTimerProc

IMPLEMENT_DYNCREATE(CWatchDog, CWinThread)

BOOL CWatchDog::InitInstance()
{
// TODO: perform and per-thread initialization here
return TRUE;
}

int CWatchDog::ExitInstance()
{
// TODO: perform any per-thread cleanup here
return CWinThread::ExitInstance();
}

BOOL CWatchDog::IsIdleMessage( MSG* pMsg )
{
if ( !CWinThread::IsIdleMessage( pMsg ) || ( pMsg->message ==
WM_TIMER ) )
****
This code should not exist. Drop this whole function!
****
{
return FALSE;
}
return TRUE;
}



BEGIN_MESSAGE_MAP(CWatchDog, CWinThread)
//{{AFX_MSG_MAP(CWatchDog)
// NOTE - the ClassWizard will add and remove mapping macros here.

//}}AFX_MSG_MAP

ON_THREAD_MESSAGE(WM_TIMER, OnTimer)
****
Why not do something very simple: ON_WM_TIMER()?

You have added tons of complexity to what is a trivial problem.
****

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWatchDog message handlers

void CWatchDog::Monitor(CString sFileName, HWND hWnd, UINT iMessage,
int iFrequency, int iTimeout)
{
//g_iTimer = ::SetTimer(NULL, NULL, iFrequency, (TIMERPROC)
OnTimerProc);

g_iTimer = SetTimer(NULL, 0, iFrequency, NULL);
g_hWnd = hWnd;
g_iMessage = iMessage;
****
Why not
SetTimer(iFrequency, NULL);
which is so much simpler?
****
}


void CWatchDog::OnTimer(WPARAM wParam, LPARAM lParam)

{
if ((UINT) wParam == g_iTimer)
{
PostMessage(g_hWnd, g_iMessage, WPARAM (0), LPARAM (0));
}
}
****
You do not need a g_iTmer, g_hWnd, or g_iMessage here, if this were a handler for
WM_TIMER. Get rid of them. I can't even imagine why they are needed at all, since they
coudl be member variables of the CWatchDog class.

Treat tasks that require global variables as deeply suspect.
joe
****

Thanks in advance,
Stefano
Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.



Relevant Pages

  • Thread and Timer
    ... I'd like to use a timer inside a thread. ... CALLBACK and handle in OnTimer I never get the message. ... UINT g_iMessage; ... PostMessage, LPARAM ); ...
    (microsoft.public.vc.mfc)
  • Re: Variable of Timer ?
    ... UINT SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* ... The timer identifier of the new timer if the function is successful. ... to the KillTimer function to destroy the timer. ...
    (microsoft.public.vc.mfc)
  • Re: EndInvoke still required?
    ... and there will never be another receive callback to ... You could put a timer on the Form, or run a dedicated consumer thread. ... And creating a consumer thread for this one purpose seems wasteful as ... A single extra consumer thread isn't really that big of a deal, and it's not like queuing something on the thread pool is completely cost-free wouldn't otherwise have to worry about). ...
    (microsoft.public.dotnet.framework)
  • Re: SetTimer not working
    ... I have a welcome dialog which registers my users to a web server just after ... have the message pump stop. ... The problem is the timer isn't working while the lengthy procesing is ... Start a thread or an asynchronous I/O operation and return to the main message pump. ...
    (microsoft.public.vc.mfc)
  • Re: [PATCH 2/4] Add cpufreq driver for the IBM PowerPC 750GX
    ... to delete the timer, and then manually set the frequency. ... The first is in the switch callback, ... means the call to _modify_PLLin _target worked. ...
    (Linux-Kernel)