WriteFile在使用WaitCommEvent时挂起应用程序

时间:2015-10-06 07:00:01

标签: c winapi serial-port readfile writefile

我正在使用事件驱动的方法来解决使用win32编程进行串行端口通信的问题。我的通信句柄创建为:

hComm = CreateFile(lpszCommName, GENERIC_READ | GENERIC_WRITE, 0,
    NULL, OPEN_EXISTING, 0, NULL);

我将我的CommTimeouts设置为:

    commTimeout.ReadIntervalTimeout = MAXWORD;
    commTimeout.ReadTotalTimeoutConstant = 0;
    commTimeout.ReadTotalTimeoutMultiplier = 0;
    commTimeout.WriteTotalTimeoutConstant = 0;
    commTimeout.WriteTotalTimeoutMultiplier = 0;

我为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);

My Wrifile进入WndProc,当WM_CHAR被触发时,它会向通信设备发送字符:

    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
    }   

我的问题是每次WriteFile()被调用我的应用程序挂起,我必须强制关闭它。如果我在我的读取线程中注释掉WaitCommEvent()它工作正常,但我无法阅读。任何指针都将不胜感激。感谢

1 个答案:

答案 0 :(得分:0)

这是同步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
    }  

WaitCommEvent在取消时返回FALSE。因此,WaitCommEvent之后的代码将不会被执行。

但是,在极端情况下,调用ReadFile函数的线程有可能在WndProc到WriteFile之前重新调用WaitCommEvent函数。如果发生这种情况,则需要单独处理。当WaitCommEvent返回FALSE时,可能会有一点延迟。