2009-08-18 211 views
1

我正在使用串行端口与远程诊断设备进行通信。SerialPort.DataReceived重复订阅/取消订阅

来自远程设备的响应长度因命令而异,但会提前知道。所以,目前我发送命令并等待接收到所需数量的响应字节。

无论何时我没有主动请求数据,我都会订阅'SerialPort.DataReceived'事件。这个事件的处理程序只是简单地将任何'主动'收到的数据转储到日志中(通常只有在远程设备意外重启时才会收到未经请求的数据,等等)。

在某些情况下,我想以大约60Hz的速率发送命令。

我的问题是,每次我调用我的'SendCommand'方法来主动请求数据时,是否最好取消订阅/订阅'SerialPort.DataReceived'事件,还是应该单独保留事件订阅,并且只需切换布尔型' TransferInProgress'标志DataReceived处理程序可用于在我主动请求时忽略传入数据?

下面是当前实现:

public virtual bool SendCommand(byte[] command, ref byte[] response) { 

    try { 
     TransferInProgress = true; 
     OnTransferStarted(); 

     // temporarily unsubscribe since we're actively soliciting data 
     _port.DataReceived -= 
      new SerialDataReceivedEventHandler(SerialPort_DataReceived); 

     _port.DiscardInBuffer(); 
     _port.Write(command, 0, command.Length); 
     OnCommandSent(command); 

     // read the requested number of response bytes 
     int responseBytesRead = 0; 

     while (responseBytesRead < response.Length) { 
      responseBytesRead += 
       _port.Read(response, responseBytesRead, (response.Length - responseBytesRead)); 
     } 

     OnCommandResponseReceived(response); 
     return true; 
    } 
    catch (Exception ex) { 
     OnCommandSendFailed(ex.Message); 
     return false; 
    } 
    finally { 
     _port.DataReceived += 
      new SerialDataReceivedEventHandler(SerialPort_DataReceived); 
     OnTransferComplete(); 
     TransferInProgress = false; 
    } 
} 

-Trevor

回答

0

你有没有想过在一个地方处理所有的数据接收?您可以将您发送的命令视为火灾并忘记,解析收到的响应数据。如果响应没有识别标题,并且知道如何解析它们的唯一方法是知道您发送了哪个命令以及响应的长度,那么您可以跟踪队列中发送的命令。可行的方法是,在您的数据接收处理程序中,您将检查您正在等待响应的命令队列,然后像现在一样解析收到的数据。

长话短说,我会建议在一个地方处理所有传入的数据。

+0

我喜欢使用队列来跟踪命令的想法,但我想知道如何能够检测未经请求的数据?我如何能够确定远程设备是否使用此方法在命令之间触发了几个字节? (注意:远程设备偶尔会重置自身并发送一些“启动”类型的字节,不幸的是,我无法控制它)。 – user158485 2009-08-18 16:48:18

+0

您仍然会在您的数据接收处理程序中检测到未经请求的数据,但您会知道它是未经请求的,因为您的“SentCommandsQueue”中没有命令。 我在串口通信中遇到了类似的问题,你必须缓冲你接收到的数据,并将解出重置消息的答案拼凑在一起。一旦你有完整的回应,从你的队列中删除命令。由于重置字节似乎对序列的开头有某种签名,因此您应该能够轻松解析它们。 – nathan 2009-08-18 16:57:44

+0

我想我可以实现像这样的东西。我唯一的预留是复位字节并不总是相同的(按顺序或数量),所以如果在正常命令之间接收到复位数据,最终可能会产生意外偏移。这就是说,我相信这个特殊的串口设备有一个选项来启用命令回显。在解析响应数组时,我可以使用echo作为标识头。 – user158485 2009-08-18 17:59:14

0

如果我理解正确的是简单地处理在DataReceived处理所有接收数据,或者你有一个其他的选择我的意见。

如果实际请求之间收到的数据不多,您可以在传输请求之前先读取缓冲区并记录下来。串行驱动程序接收缓冲区可能足以存储少量数据。然后发送请求并读入响应。这很可能是更简单的方法和更简单的代码。

0

我通常会切换布尔值。通过订阅/取消订阅,您可能会多次订阅相同的事件。例如,在您的代码中,如果OnTransferStarted()引发异常,您将订阅两次DataReceived事件。