首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >串行端口和重叠I/O操作期间的错误处理

串行端口和重叠I/O操作期间的错误处理
EN

Stack Overflow用户
提问于 2009-08-22 14:48:50
回答 1查看 3.5K关注 0票数 1

我最近一直在做串行通信,所以我准备了一个类,它是所有Windows API函数的简单接口,负责读取、写入等。该类中的所有I/O操作都是异步处理的。

在我开始我的问题之前,让我向您展示如何从串口写入和读取数据(这只是读取函数,因为写入函数的结构完全相同,所以没有必要同时显示这两个函数)。

代码语言:javascript
复制
function TSerialPort.Read(var pBuffer; const lBufferSize: Cardinal): Cardinal;
var
  lOverlapped: OVERLAPPED;
  lLastError: Cardinal;
  lEvent: TEvent;
begin
  lEvent := TEvent.Create(nil, True, False, '');
  try
    FillChar(lOverlapped, SizeOf(lOverlapped), 0);
    lOverlapped.hEvent := lEvent.Handle;

    if not ReadFile(FSerialPortHandle, pBuffer, lBufferSize, Result, @lOverlapped) then
    begin
      lLastError := GetLastError;
      if (lLastError <> ERROR_IO_PENDING) and (lLastError <> ERROR_SUCCESS) then
        raise Exception.Create(SysErrorMessage(lLastError));

      case lEvent.WaitFor(INFINITE) of
        wrSignaled:
          if not GetOverlappedResult(FSerialPortHandle, lOverlapped, Result, False) then
            raise Exception.Create(SysErrorMessage(GetLastError));

        wrError:
          begin
            lLastError := lEvent.LastError;
            //this is a call to Windows.CancelIo(FSerialPortHandle);
            if Self.CancelIO() then
              lEvent.WaitFor(INFINITE);
            raise Exception.Create(SysErrorMessage(lLastError));
          end;
      end;
    end;
  finally
    FreeAndNil(lEvent);
  end;
end;

在您问我为什么在此函数等待读取操作完成时打开串口进行重叠操作之前,这里是我的解释-只有当以这种方式打开串口时,我才能指定WaitCommEvent()方法等待事件的时间。如果我为非重叠操作打开端口,WaitCommEvent()将会阻塞,直到串行端口上出现一个事件,而这并不总是会导致调用线程永远阻塞。

不过,让我们关注上面的Read()函数。

1)首先,我没有任何时间限制地等待事件的设置。有没有可能因为某种原因,当前线程会永远阻塞?我不知道我是否可以百分之百地确定事件迟早会由异步执行读取操作的线程设置。我知道当串行端口的读取超时都设置为0时,读取操作直到读取给定数量的字节时才会完成,但这是我知道的一种行为。我的问题涉及到一些意外的情况,这些情况会导致事件永远不会被设置,WaitFor()方法会永远等待--这种情况有可能发生吗?

2) WaitFor()可能会返回wrError,通知在等待操作期间发生了一些错误(但这与重叠的读取操作没有任何关系,对吧?)。因此,我认为我不应该再等待读操作完成,因为事件句柄可能不再可用,对吧?因此,我调用CancelIO()方法来取消读取操作,等待异步执行取消读取的线程设置事件,然后才引发异常。我等待该线程取消读取,因为如果我立即离开Read()方法(没有取消I/O),我会导致该线程将其数据(重叠的记录数据)写入到不再有效的局部变量中,对吧?另一方面,在引发异常之前,当前线程会因为WaitFor(INFINITE)调用而被永久阻塞吗?

如果您能告诉我上述说法是否属实,并对它们发表意见,我将不胜感激。

非常提前感谢您。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-08-22 15:42:36

出于好奇:为什么不使用现有的串行组件?

我使用TurboPower Async接收GPS消息,但还有很多其他免费的:http://www.efg2.com/Lab/Library/Delphi/IO/PortIO.htm

其中大多数允许您在更高的级别上进行串行通信,为您抽象出所有较低级别的IO和线程。

这样,您只需编写一个onreceive处理程序来接收,并调用send()来发送内容。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1316132

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档