C++ Win32在COM端口上重叠读取文件返回错误\u操作\u中止

C++ Win32在COM端口上重叠读取文件返回错误\u操作\u中止,c++,winapi,serial-port,C++,Winapi,Serial Port,好吧,一个给蜂巢般的头脑 直到今天,我的代码在许多系统上都运行得很好,并部署在许多站点上。它涉及线程从串行端口读取和写入数据 尝试签出一个新设备时,我的代码被995错误_操作_在读取文件后调用GetOverlappedResult时中止的错误所淹没。有时读取会起作用,有时我会出现这个错误。令人惊讶的是,只要忽略错误并重试就可以在不丢失任何数据的情况下工作。不需要ClearCommercor 这是片段 if (!ReadFile(handle,&c,1,&read, &ol

好吧,一个给蜂巢般的头脑

直到今天,我的代码在许多系统上都运行得很好,并部署在许多站点上。它涉及线程从串行端口读取和写入数据

尝试签出一个新设备时,我的代码被995错误_操作_在读取文件后调用GetOverlappedResult时中止的错误所淹没。有时读取会起作用,有时我会出现这个错误。令人惊讶的是,只要忽略错误并重试就可以在不丢失任何数据的情况下工作。不需要ClearCommercor

这是片段

if (!ReadFile(handle,&c,1,&read, &olap))
    {
        if (GetLastError() != ERROR_IO_PENDING)
        {
            logger().log_api(LOG_ERROR,"ser_rx_char:ReadFile");
            throw Exception("ser_rx_char:ReadFile");
        }
    }

    WaitForSingleObjectEx(r_event, INFINITE, true);  // alertable, so, thread can be closed correctly.

    if (GetOverlappedResult(handle,&olap,&read, TRUE) != 0)
    {
        if (read != 1)
            throw Exception("ser_rx_char: no data");

        logger().log(LOG_VERBOSE,"read char %d ( read = %d) ",c, read);
    }
    else
    {
        DWORD err = GetLastError();
        if (err != 995)   //Filters our ERROR_OPERATION_ABORTED
        {
            logger().log_api(LOG_ERROR,"ser_rx_char: GetOverlappedResult");
            throw Exception("ser_rx_char:GetOverlappedResult");
        }
    }
我的第一个猜测是责怪COM端口驱动程序,我以前从未使用过它(仅供参考,它是Blackmagic Decklink上的RS422端口),但这感觉像是在逃避责任

哦,还有Vista SP1 32位商业版,我的罪


在我把这个问题归结为“其他人的问题”之前,有人知道是什么导致了这个问题吗?

在读取文件之前,您是如何设置重叠结构的我总是把它们归零(显然,除了hEvent),这可能是迷信的一部分,但我觉得这在过去给我带来了一个问题

我担心责怪司机(如果不是MS,而不仅仅是参考资料中的一个小改动)并不是完全不现实的。编写COM驱动程序是一件极其复杂的事情,而测试它的困难在于,所有编写的应用程序使用串行端口及其IOCTL的方式都略有不同

另一个常见问题是不设置整个端口-例如不调用SetCommTimeout或SetupComm。我不知道你是否犯了这样的错误,但我遇到过一些人,他们说他们没有使用超时,而实际上他们的意思是他们没有调用SetCommTimeout,所以他们正在使用它们,但不知道它们设置为什么


对于第三方COM驱动程序来说,这类东西可能是致命的,因为人们经常用MS驱动程序处理旧的垃圾,并且它在其他设备上并不总是一样的工作。

除了将重叠部分归零之外,您还可以检查如何设置olap.hEvent,也就是说,您对CreateEvent的参数是什么?如果您正在创建一个预先发出信号的事件(即CreateEvent的第三个参数为TRUE),我希望立即返回。另外,不要忘记,如果将manualReset(CreateEvent的第二个参数)指定为FALSE,则GetOverlappedResult()将有助于清除事件,这可能解释为什么它会在第二次工作


从您的代码片段中无法判断这两种情况是否会影响您-希望这能有所帮助。

我同意超时似乎是一个可能的原因,特别是因为没有输入丢失,ReadFile调用一次只读取一个字节。但是,如果应用程序正确设置端口,则可以责怪驱动程序,包括MS的驱动程序。我正在清除重叠结构(除了hEvent),并在CommTimeout中的所有字段中使用零调用SetCommTimeout。我尝试更改为非重叠I/o,得到了相同的结果。是时候尝试另一个通信端口了……我认为这不是您的问题,但您没有正确使用
WaitForSingleObjectEx
。您应该检查(1)
dwWait==WAIT\u OBJECT\u 0
或(2)
dwWait==WAIT\u TIMEOUT&&dwError==ERROR\u IO\u PENDING