I am encoutering a issues with win32 programming doing a serial port communication using a event-driven approach. I have my communication handle created as:
hComm = CreateFile(lpszCommName, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, NULL);
and i set my CommTimeouts as:
commTimeout.ReadIntervalTimeout = MAXWORD;
commTimeout.ReadTotalTimeoutConstant = 0;
commTimeout.ReadTotalTimeoutMultiplier = 0;
commTimeout.WriteTotalTimeoutConstant = 0;
commTimeout.WriteTotalTimeoutMultiplier = 0;
I created a thread for ReadFile which looks like this:
SetCommMask(hComm, EV_RXCHAR);
while (isConnected)
{
if (WaitCommEvent(hComm, &dwEvent, NULL)) //If i comment out this block my write file will work fine
{
ClearCommError(hComm, &dwError, &cs);
if ((dwEvent & EV_RXCHAR) && cs.cbInQue)
{
if (!ReadFile(hComm, str, cs.cbInQue, &read_byte, NULL))
/* Process error*/
else if (read_byte)
/* Print to screen */
}
else {
/* Process error*/
}
}
}
PurgeComm(hComm, PURGE_RXCLEAR);
My Wrifile goes into WndProc which sends characters to the communication device when WM_CHAR is triggered:
VOID Write_To_Serial(WPARAM wParam, HWND hwnd){
DWORD write_byte;
char str[10];
sprintf_s(str, "%c", (char)wParam); //Convert wParam to a string
WriteFile(hComm, str, strlen(str), &write_byte, NULL)//Program hangs here
}
My problem is everytime WriteFile() is called my application hangs and I have to force to close it. And if I comment out the WaitCommEvent() in my read thread it works fine, but I can't read then.Any pointers would be appreciated. thanks
This is the expected behavior of Synchronous IO operations.
As per the following description in Serial Communications article in MSDN (https://msdn.microsoft.com/en-us/library/ff802693.aspx),
It is the responsibility of the application to serialize access to the port correctly. If one thread is blocked waiting for its I/O operation to complete, all other threads that subsequently call a communications API will be blocked until the original operation completes. For instance, if one thread were waiting for a ReadFile function to return, any other thread that issued a WriteFile function would be blocked.
WriteFile has to wait until WaitCommEvent function has completed its operation.
A small workaround would be to cancel the pending WaitCommEvent operation (for instance by using CancelIoEx API) when WriteFile needs to be invoked.
VOID Write_To_Serial(WPARAM wParam, HWND hwnd){
DWORD write_byte;
char str[10];
sprintf_s(str, "%c", (char)wParam); //Convert wParam to a string
CancelIoEx(hComm, NULL);
WriteFile(hComm, str, strlen(str), &write_byte, NULL);//Program hangs here
}
WaitCommEvent returns FALSE when canceled. Hence,the code following WaitCommEvent will not be executed.
However, in extreme case, there is a chance, where the thread invoking the ReadFile function, re invokes the WaitCommEvent function, before WndProc gets to WriteFile. If this occurs, it needs to be handled separately. Maybe a small delay when WaitCommEvent returns FALSE would do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With