-
March 28th, 2007, 06:03 AM
#1
Serial port WaitForMultipleObjects() problem
The call to WaitForMultipleObjects() does not return, it seems the event for the serial port does not get signalled. I was under the impression that sending data to the port will cause the event to be signalled. Am i doing something wrong here?
Code:
UINT CMyserialportView::ReaderThread(LPVOID p)
{
TRACE("\nThread ReaderThread() >");
CSerialParameters* parms = (CSerialParameters *)p;
OVERLAPPED ovl = {0};
ovl.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if(ovl.hEvent == NULL)
{ /* failed */
DWORD err = ::GetLastError();
parms->m_pWndNotifyee->PostMessage(UWM_READER_SHUTTING_DOWN, (WPARAM)err);
return 0;
} /* failed */
DWORD shutdown; // reason for shutdown
HANDLE waiters[2];
waiters[0] = parms->m_hShutdown;
waiters[1] = ovl.hEvent;
#define MAX_BUFFER_SIZE 100
BOOL running = TRUE;
DWORD bytesRead;
while(running)
{ /* read loop */
BYTE buffer[MAX_BUFFER_SIZE];
BOOL ok = ::ReadFile(parms->m_hCom, buffer, MAX_BUFFER_SIZE - 1, &bytesRead, &ovl);
if(!ok)
{ /* error */
DWORD err = ::GetLastError();
if(err != ERROR_IO_PENDING)
{ /* read error */
shutdown = err;
running = FALSE;
continue;
} /* read error */
// otherwise, it is ERROR_IO_PENDING
DWORD result = ::WaitForMultipleObjects(2, waiters, FALSE, INFINITE);
//DWORD result = ::WaitForSingleObject(ovl.hEvent, INFINITE);
switch(result)
{ /* wait */
case WAIT_OBJECT_0: // shutdown
::CancelIo(parms->m_hCom);
shutdown = ERROR_SUCCESS; // clean shutdown
running = FALSE;
continue;
case WAIT_OBJECT_0 + 1: // I/O complete
ok = ::GetOverlappedResult(parms->m_hCom, &ovl, &bytesRead, TRUE);
if(!ok)
{ /* GetOverlappedResult failed */
DWORD err = ::GetLastError();
running = FALSE;
continue;
} /* GetOverlappedResult failed */
break;
default:
{ /* trouble */
shutdown = ::GetLastError();
ASSERT(FALSE); // failure
running = FALSE;
continue;
} /* trouble */
} /* wait */
} /* error */
// if we get here, either the ReadFile worked immediately, or we waited for completion
if(bytesRead == 0)
continue; // nothing was read
buffer[bytesRead] = '\0'; // assumes 8-bit characters without embedded NUL
CString* s = new CString((LPCSTR)buffer);
parms->m_pWndNotifyee->PostMessage(UWM_DATA_READ, (WPARAM)s);
} /* read loop */
parms->m_pWndNotifyee->PostMessage(UWM_READER_SHUTTING_DOWN, (WPARAM)shutdown);
::CloseHandle(ovl.hEvent);
return 0; // we're gone. You may choose to do something different
} // CMyClass::ReaderThread
Time is fun when you're having flies
-
March 28th, 2007, 06:11 AM
#2
Re: Serial port WaitForMultipleObjects() problem
WaitForMultipleObjects waits for all objects, so perhaps it is the other event, parms->m_hShutdown, that is not signalled?
Regards / Z
Nobody cares how it works as long as it works
-
March 28th, 2007, 06:37 AM
#3
Re: Serial port WaitForMultipleObjects() problem
No i pass in FALSE as one of the parameters which means if one of the parameters is signalled the WaitForMultipleObjects() returns.
bWaitAll
[in] If this parameter is TRUE, the function returns when the state of all objects in the lpHandles array is signaled. If FALSE, the function returns when the state of any one of the objects is set to signaled. In the latter case, the return value indicates the object whose state caused the function to return.
Time is fun when you're having flies
-
March 28th, 2007, 06:51 AM
#4
Re: Serial port WaitForMultipleObjects() problem
And you did open the com port with FILE_FLAG_OVERLAPPED ?
Regards / Z
Nobody cares how it works as long as it works
-
March 28th, 2007, 06:56 AM
#5
Re: Serial port WaitForMultipleObjects() problem
This is the OnInitialUpdate() in which i open the serial port and create/start the threads.....
Code:
void CMyserialportView::OnInitialUpdate()
{
CView::OnInitialUpdate();
m_hCom = ::CreateFile( "\\\\.\\COM2", // filename
GENERIC_READ|GENERIC_WRITE, // desired access
0, // exclusive
NULL, // security irrelevant
OPEN_EXISTING, // it has to be there
FILE_FLAG_OVERLAPPED, // open asynchronous
NULL); // template file
if(m_hCom == NULL)
{
AfxMessageBox("Failed to open COM port", 0);
return;
}
// Create writer thread
m_pSerialWriter = (CSerialWriter*)AfxBeginThread(
RUNTIME_CLASS(CSerialWriter),
THREAD_PRIORITY_NORMAL, // priority
0, // default stack size
CREATE_SUSPENDED); // don't run right away
if(m_pSerialWriter == NULL)
{
AfxMessageBox("Could not create writer thread",0);
return;
}
HANDLE m_hShutDown = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if(m_hShutDown == NULL)
{
AfxMessageBox("Could not create shutdown event",0);
return;
}
m_pSerialWriter->m_pParameters = new CSerialParameters(m_hCom, this, m_hShutDown);
m_pSerialWriter->ResumeThread();
CString* myS = new CString("010203040506070809A0010203040506070808");
m_pSerialWriter->PostThreadMessage(UWM_DATA_SEND, (WPARAM)myS, (LPARAM)0);
// Create reader thread
AfxBeginThread(ReaderThread, m_pSerialWriter->m_pParameters);
}
Time is fun when you're having flies
-
March 28th, 2007, 07:15 AM
#6
Re: Serial port WaitForMultipleObjects() problem
After opening the port (::CreateFile(...) ) you have to set the DCB (GetCommState/SetCommState) and port TIMEOUTs (GetCommTimeouts/SetCommTimeouts), something like:
Code:
// declared in header: COMMTIMEOUTS m_CommTimeOuts;
.......
if(::GetCommTimeouts(m_hCom, &m_CommTimeOuts))
{
COMMTIMEOUTS TimeOuts(m_CommTimeOuts);
// correct these values
TimeOuts.ReadIntervalTimeout = 100;
TimeOuts.ReadTotalTimeoutConstant = 100;
TimeOuts.ReadTotalTimeoutMultiplier = 10;
TimeOuts.WriteTotalTimeoutConstant = 10;
TimeOuts.WriteTotalTimeoutMultiplier= 100;
if(::SetCommTimeouts(m_hCom, &TimeOuts))
{
// ready to work with the port to read...
Otherwise, your reader thread might hang on waiting for the next character.
-
March 28th, 2007, 07:28 AM
#7
Re: Serial port WaitForMultipleObjects() problem
If VictorN's suggestion does not help, plz post code for CSerialWriter also
Nobody cares how it works as long as it works
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|