Som*_*uts 5 c winapi serial-port writefile readfile
我遇到了使用事件驱动方法进行串行端口通信的 win32 编程问题。我将我的通信句柄创建为:
hComm = CreateFile(lpszCommName, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, NULL);
Run Code Online (Sandbox Code Playgroud)
我将 CommTimeouts 设置为:
commTimeout.ReadIntervalTimeout = MAXWORD;
commTimeout.ReadTotalTimeoutConstant = 0;
commTimeout.ReadTotalTimeoutMultiplier = 0;
commTimeout.WriteTotalTimeoutConstant = 0;
commTimeout.WriteTotalTimeoutMultiplier = 0;
Run Code Online (Sandbox Code Playgroud)
我为 ReadFile 创建了一个线程,如下所示:
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);
Run Code Online (Sandbox Code Playgroud)
我的 Wrifile 进入 WndProc,当 WM_CHAR 被触发时,WndProc 将字符发送到通信设备:
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
}
Run Code Online (Sandbox Code Playgroud)
我的问题是每次调用 WriteFile() 时我的应用程序都会挂起,我必须强制关闭它。如果我在我的阅读线程中注释掉 WaitCommEvent() 它工作正常,但我无法阅读。任何指针将不胜感激。谢谢
小智 2
这是同步 IO 操作的预期行为。
根据 MSDN 串行通信文章 ( https://msdn.microsoft.com/en-us/library/ff802693.aspx ) 中的以下描述,
应用程序有责任正确序列化对端口的访问。如果一个线程因等待其 I/O 操作完成而被阻塞,则随后调用通信 API 的所有其他线程都将被阻塞,直到原始操作完成。例如,如果一个线程正在等待 ReadFile 函数返回,则发出 WriteFile 函数的任何其他线程都将被阻塞。
WriteFile 必须等待 WaitCommEvent 函数完成其操作。
一个小的解决方法是在需要调用 WriteFile 时取消挂起的 WaitCommEvent 操作(例如通过使用 CancelIoEx API)。
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
}
Run Code Online (Sandbox Code Playgroud)
取消时 WaitCommEvent 返回 FALSE。因此,WaitCommEvent 之后的代码将不会被执行。
然而,在极端情况下,调用 ReadFile 函数的线程有可能在 WndProc 到达 WriteFile 之前重新调用 WaitCommEvent 函数。如果出现这种情况,需要单独处理。也许当 WaitCommEvent 返回 FALSE 时稍微延迟一下就可以了。