Serial coms worker thread not working
-
Hi All, I wondered if someone can shed some light on what might be going on here. I have created the worker thread (code below) and when my system first boots up and I run through debug I find that the thread doesn't fire off the PostMessage(UWM_DATA_READ) until the buffer is full up....what I want it to do is fire it off when ever it reads in something. The interesting part is that if I stop the application and open Hyperterminal on the same com port then close it and then rerun the application it works as I intended???? Does anyone have any ideas what is going on?????? Cheers Jim
UINT CMyDlg::monitorThread(LPVOID pParam)
{
DWORD dwRead;
DWORD dwRes;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
struct PTZCommStruct *pPTZStruct = (struct PTZCommStruct *)pParam;// Create the overlapped event. osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if(osReader.hEvent == NULL) { // Error creatiing overlapped event, abort. DWORD err = ::GetLastError(); pPTZStruct->pWnd->PostMessage(UWM\_READER\_SHUTTING\_DOWN, (WPARAM)err); return 0; } while(pPTZStruct->nPTZCommTerminate == 0) { if(!fWaitingOnRead) { // Issue read Operation. BOOL tmp = ReadFile(m\_hPTZCtrlPort, PTZbuffer, MAX\_BUFFER\_SIZE, &dwRead, &osReader); if(!tmp) { if(GetLastError() != ERROR\_IO\_PENDING) // read not delayed { // Error in comms - report!!! return 0; } else { fWaitingOnRead = TRUE; } } else { // \*\*\*Read the data pPTZStruct->pWnd->PostMessage(UWM\_DATA\_READ); } } else { dwRes = WaitForSingleObject(osReader.hEvent, READ\_TIMEOUT); switch(dwRes) { // Read Completed case WAIT\_OBJECT\_0: if(!GetOverlappedResult(m\_hPTZCtrlPort, &osReader, &dwRead, FALSE)) { DWORD dwError = GetLastError(); switch(dwError) { case ERROR\_HANDLE\_EOF: return 0; break; case ERROR\_IO\_PENDING: return 0; break; case ERROR\_IO\_INCOMPLETE: return 0; break; case ERROR\_OPERATION\_ABORTED: return 0; break; default: // error in comms - report Dump1("Serial Read Error %d\\r\\n", ::GetLastError()); return 0; break; } } else { // \*\*\*Read the Data pPTZStruct->pWnd->PostMessage(UWM\_DATA\_READ); } fWaitingOnRead = FALSE; break; case WAIT\_TIMEOUT:
-
Hi All, I wondered if someone can shed some light on what might be going on here. I have created the worker thread (code below) and when my system first boots up and I run through debug I find that the thread doesn't fire off the PostMessage(UWM_DATA_READ) until the buffer is full up....what I want it to do is fire it off when ever it reads in something. The interesting part is that if I stop the application and open Hyperterminal on the same com port then close it and then rerun the application it works as I intended???? Does anyone have any ideas what is going on?????? Cheers Jim
UINT CMyDlg::monitorThread(LPVOID pParam)
{
DWORD dwRead;
DWORD dwRes;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
struct PTZCommStruct *pPTZStruct = (struct PTZCommStruct *)pParam;// Create the overlapped event. osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if(osReader.hEvent == NULL) { // Error creatiing overlapped event, abort. DWORD err = ::GetLastError(); pPTZStruct->pWnd->PostMessage(UWM\_READER\_SHUTTING\_DOWN, (WPARAM)err); return 0; } while(pPTZStruct->nPTZCommTerminate == 0) { if(!fWaitingOnRead) { // Issue read Operation. BOOL tmp = ReadFile(m\_hPTZCtrlPort, PTZbuffer, MAX\_BUFFER\_SIZE, &dwRead, &osReader); if(!tmp) { if(GetLastError() != ERROR\_IO\_PENDING) // read not delayed { // Error in comms - report!!! return 0; } else { fWaitingOnRead = TRUE; } } else { // \*\*\*Read the data pPTZStruct->pWnd->PostMessage(UWM\_DATA\_READ); } } else { dwRes = WaitForSingleObject(osReader.hEvent, READ\_TIMEOUT); switch(dwRes) { // Read Completed case WAIT\_OBJECT\_0: if(!GetOverlappedResult(m\_hPTZCtrlPort, &osReader, &dwRead, FALSE)) { DWORD dwError = GetLastError(); switch(dwError) { case ERROR\_HANDLE\_EOF: return 0; break; case ERROR\_IO\_PENDING: return 0; break; case ERROR\_IO\_INCOMPLETE: return 0; break; case ERROR\_OPERATION\_ABORTED: return 0; break; default: // error in comms - report Dump1("Serial Read Error %d\\r\\n", ::GetLastError()); return 0; break; } } else { // \*\*\*Read the Data pPTZStruct->pWnd->PostMessage(UWM\_DATA\_READ); } fWaitingOnRead = FALSE; break; case WAIT\_TIMEOUT:
Wow, it really seems that you like to complicate your life. If you are doing that in a separate thread, why are you using OverlappedIO ? You could simply use a blocking read that returns when data is available. Anyway, that's not the source of your problem. From your description, it really sounds like you didn't set the comm timeouts. Thus, when you start hyperterminal, the timeout settings are changed and that's why the behavior is different afterwards. To change the comm timeouts, you can use the SetCommTimeouts[^] function.
Cédric Moonen Software developer
Charting control [v1.5] OpenGL game tutorial in C++ -
Wow, it really seems that you like to complicate your life. If you are doing that in a separate thread, why are you using OverlappedIO ? You could simply use a blocking read that returns when data is available. Anyway, that's not the source of your problem. From your description, it really sounds like you didn't set the comm timeouts. Thus, when you start hyperterminal, the timeout settings are changed and that's why the behavior is different afterwards. To change the comm timeouts, you can use the SetCommTimeouts[^] function.
Cédric Moonen Software developer
Charting control [v1.5] OpenGL game tutorial in C++