Win32在COM端口上的重叠读文件返回ERROR_OPERATION_ABORTED错误

3

好的,这是一个关于IT技术的翻译请求...

我有一段代码,之前在许多系统上都运行良好,并部署在许多站点上。它涉及到从串口读写数据的线程。

在尝试检查新设备时,我的代码被大量的995 ERROR_OPERATION_ABORTED错误所淹没,在调用ReadFile后调用GetOverlappedResult。有时读取会成功,有时我会得到这个错误。只是忽略错误并重试 - 令人惊讶的是 - 可以在不丢失任何数据的情况下工作。不需要ClearCommError。

以下是代码片段。

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端口驱动程序,我以前没有使用过(FYI,这是Blackmagic Decklink上的RS422端口),但这感觉像是推卸责任。

哦,对了,我用的是Vista SP1 Business 32位版本,真是自讨苦吃。

在我把这个问题归咎于“别人的问题”之前,有人有什么想法会导致这种情况吗?


1
我不认为这是你的问题,但你没有正确使用WaitForSingleObjectEx。你应该检查(1)dwWait == WAIT_OBJECT_0或(2)dwWait == WAIT_TIMEOUT && dwError == ERROR_IO_PENDING - jww
2个回答

4
你在ReadFile之前是如何设置OVERLAPPED结构的?- 我总是将它们归零(除了hEvent,显然),这可能有点迷信,但我有一种感觉,它曾经给我带来过问题。
如果责备驱动程序(如果它不是微软的,也不仅仅是对参考的微小调整),那么这并不完全是不现实的。编写COM驱动程序是一件非常复杂的事情,测试它的困难在于每个编写的应用程序都使用串行端口及其IOCTL略有不同。
另一个常见问题是没有设置整个端口 - 例如不调用SetCommTimeouts或SetupComm。我不知道你是否犯了这样的错误,但我遇到过说他们没有使用超时时间的人,实际上他们是指他们没有调用SetCommTimeouts,因此他们使用超时时间,但不知道超时时间设置为多少...
对于第三方COM驱动程序来说,这种情况可能会很麻烦,因为人们通常可以使用任何旧的MS驱动程序,而它不总是与其他设备一样工作。

我同意超时看起来是一个可能的原因,特别是因为没有输入丢失,而ReadFile调用每次只读取一个字节。然而,如果应用程序正确设置了端口,那么归咎于驱动程序是合理的,包括如果它是微软的驱动程序。 - Windows programmer
我正在清除OVERLAPPED结构(除了hEvent),并在COMMTIMEOUTS中将所有字段都设置为零,然后调用SetCommTimeouts。我尝试更改为非重叠I/O,但结果相同。是时候尝试另一个通信端口了... - Roddy

0

除了将OVERLAPPED清零之外,您还应该检查如何设置olap.hEvent,也就是说,您对CreateEvent的参数是什么?如果您创建的事件是预先标记的(即CreateEvent的第三个参数为TRUE),我会期望立即返回。此外,请不要忘记,如果您将manualReset(CreateEvent的第二个参数)指定为FALSE,则GetOverlappedResult()将有助于为您清除事件-这可能解释了为什么第二次运行它可以正常工作。

从您的片段中无法确定这些是否会影响您-希望这可以帮助您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接