killing timer thread causes prefetch abort
I have a class I use as a timer, CAbortableTimer(), that has, until
now, worked pretty well. But, in my current situation, I have a class
that starts a timer in its constructor and kills it in its destructor.
But, when the destructor is called sometimes I get an Access Violation.
In this case, CMyClass is allocated on the stack, so the destructor is
called by delete.
The callstack at the time of the Access Violation is, unfortunately,
junk. Can anybody tell from the code below where I might be going
wrong?
Thanks,
PaulH
CMyClass::CMyClass()
{
m_hTimer = CAbortableTimer::SetTimer(1000, &CMyClass::OnTimer,
(DWORD_PTR)this);
}
CMyClass::~CMyClass()
{
if (m_hTimer != INVALID_HANDLE_VALUE)
SetEvent(m_hTimer); //stop the timer
}
//The timer should fire every dwMilliseconds and call the timer
callback function.
//The timer can be killed by calling SetEvent on the HANDLE returned by
this function.
/*static*/ HANDLE CAbortableTimer::SetTimer(DWORD dwMilliseconds,
const LPATIMERCALLBACK
fptc,
DWORD_PTR dwUserData)
{
PTIMER_INFO pTI = new TIMER_INFO;
pTI->dwMilliseconds = dwMilliseconds;
pTI->fptc = fptc;
pTI->dwUserData = dwUserData;
pTI->hAbort = CreateEvent(NULL, TRUE, FALSE, _T("AbortEvent_" +
GUIDGen()));
if (!pTI->hAbort)
{
delete pTI;
return INVALID_HANDLE_VALUE;
}
AfxBeginThread(TimerThread, reinterpret_cast<LPVOID>(pTI));
return pTI->hAbort;
}
/*static*/ UINT CAbortableTimer::TimerThread(LPVOID lParam)
{
PTIMER_INFO pTI = reinterpret_cast<PTIMER_INFO>(lParam);
DWORD dwWait = 0;
do
{
dwWait = WaitForSingleObject(pTI->hAbort, pTI->dwMilliseconds);
if (dwWait == WAIT_TIMEOUT)
{
//timer finished
ASSERT_POINTER(pTI->fptc, LPATIMERCALLBACK);
// If the above ASSERT fires, it is likely the calling
class was
// destroyed before the timer was shut down. You should
shut down
// the timer in the destructor.
pTI->fptc(pTI->dwUserData);
}
else if (dwWait == WAIT_OBJECT_0)
{
//timer aborted
}
} while(dwWait == WAIT_TIMEOUT);
delete pTI;
return 0;
}
typedef struct _timerInfo
{
DWORD dwMilliseconds;
HANDLE hAbort;
LPATIMERCALLBACK fptc;
DWORD_PTR dwUserData;
}TIMER_INFO, *PTIMER_INFO;
typedef void (CALLBACK ATIMERCALLBACK)(DWORD_PTR dwUserData);
typedef ATIMERCALLBACK FAR *LPATIMERCALLBACK;