|
Question : Timers in CWinthread derived classes
|
|
Hi Experts,
I have a basic serial comms class. I create a new class by inheriting from my comms class and CWinthread i.e. class CRelayBox : public CWinThread, public CSerialComms { DECLARE_DYNCREATE(CRelayBox) .... }
I now want to be able to handle a timer in my derived class. In the app I have classes created as such.
One a Timer works fine and in the other it does not want to work at all. What is the correct way of doing this.
Note, I have overridden onrun because I want to continuall poll the serial port (or write to it) in the class.
Code posted below. - This is the sample that does not work. If I post a wm_timer message to the class from the view of the app, then it is a happy camper. the settimer returns ok but no WM_TIMER message ever appears. I suspect it may have to do with message qyue creation but am in the dark as to why i works in one class and not the other. This is consistant, even if I do not instantuate the working class.
Any help appretaited
Hylton
int CRelayBox::Run() { MSG msg; PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); for (;;) { if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { memset(&msg, 0, sizeof(MSG)); // clear out the old message } else { if (!PreTranslateMessage (&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
switch (msg.message) { case WM_QUIT: { return 0; } break; case WM_TIMER: { if (msg.wParam == RELAYBOX_TIMER_ID) { OnCommsTimer(msg.wParam); } else { MessageBeep(-1); } } break; } ReadSerialPort(); } }
void CRelayBox::ControledSendData(char * DataLine, char *szLogLineIn, int DataType) { memset(m_szOutDataBuf, 0, sizeof(m_szOutDataBuf)); strcpy(m_szOutDataBuf, DataLine);
if (m_bDebugging) { LogData("", m_szOutDataBuf, TCSS_DEBUG); // debug log file } if (m_bLogging) { LogData("", m_szOutDataBuf, DataType); // Out to transaction log file } m_Timer = true; SetTimer(NULL, RELAYBOX_TIMER_ID, RELAYBOX_INT , NULL); SendCommsData(m_szOutDataBuf); iRetry = 0; }
void CRelayBox::ResendData() { iRetry ++; if (iRetry > 5 ) // Put the thing out of its misery { KillTimer(NULL, RELAYBOX_TIMER_ID); m_Timer = false; PostMessage(m_AttachedWindow, CONTROL_TIMEOUT, 0, 0); } else { if (m_bDebugging) { LogData("", m_szOutDataBuf, TCSS_DEBUG); // debug log file } if (m_bLogging) { LogData("", m_szOutDataBuf, TCSS_RETRY); // Out to transaction log file } SendCommsData(m_szOutDataBuf); } }
void CRelayBox::OnCommsTimer(UINT nIDEvent) { if (!m_Timer) // Got data but message still got through { KillTimer(NULL, RELAYBOX_TIMER_ID); m_Timer = false; // For completeness } else { ResendData(); } }
|
|
Answer : Timers in CWinthread derived classes
|
|
Solved.
The thread function was being called from the main thread hence the thread context was incorrect for the timer message.
This was solved by using postthreadmessage from the main thread to the worker/ui thread. This did not initailly work as I implemented it using on_thread_message. Beacuse the ::run memeber is overloaded and the base class not called, the on_Thread_message macros did not work. When I moved the check for the message type to the run function (As I was doing with WM_CLOSE - See code above), the timer kicked in and now works as planned.
This is posted here as a solution in the hope that it may help someone else down the line.
Hylton
|
|
|
|