2016-11-16 87 views
1

我一直在使用SerialPort类在与我设计的一些外部硬件进行通信的应用程序中有一段时间。在所述硬件的调试过程中,我发现一些事情是不可靠的,最近我偶然发现了this这似乎是东西。如何更可靠地使用SerialPort类

我想落实到我的应用程序这一点,但是我对接收数据的两个问题...

所以,我挂在文章中,笔者提到,DataReceived事件是有问题的,并显示它是如何被使用的典型代码示例...

port.DataReceived += port_DataReceived; 

// (later, in DataReceived event) 
try { 
    byte [] buffer = new byte[port.BytesToRead]; 
    port.Read(buffer, 0, buffer.Length); 
    raiseAppSerialDataEvent(buffer); 
} 
catch (IOException exc) { 
    handleAppSerialError(exc); 
} 

然后笔者认为是显示了正确的方法是什么?

byte[] buffer = new byte[blockLimit]; 
Action kickoffRead = null; 

kickoffRead = delegate { 
port.BaseStream.BeginRead(buffer, 0, buffer.Length, 
     delegate (IAsyncResult ar) { 
      try { 
       int actualLength = port.BaseStream.EndRead(ar); 
       byte[] received = new byte[actualLength]; 
       Buffer.BlockCopy(buffer, 0, received, 0, actualLength); 
       raiseAppSerialDataEvent(received); 
      } 
      catch (IOException exc) { 
       handleAppSerialError(exc); 
      } 
      kickoffRead(); 
     }, null); 
    }; 
    kickoffRead(); 

我的问题围绕着使用BaseStream.BeginRead;如果我的班级里有关于这些数据的内容,应该把这些数据读出来?我的第一个想法是在DataReceived事件中,如第一个示例所示,不应使用SerialPort类,作者提到代码位于注释中的DataReceived事件中,但对于示例,显示作者没有提及的更好方法在哪里代码应该是这样我以为他仍然指的是DataReceived事件,但后来作者提到DataReceived事件本身有问题,所以......?这里的任何指导都会很棒,如果它很明显的话,我们也可以采用appologies

如果我没有提到任何有利于任何人试图回答这个问题,那么请通知我。 在此先感谢您的任何指导和/或反馈!

+0

对于程序员来说,一半的代码是非常常见的,大喊“不可靠!”,这样做使得它工作并将其声明为“优越”。 DataReceived中的标准错误是不关注e.EventType,即使您知道有字节要读取并使用Read()而不使用其返回值,也可以使用BytesToRead。没有为ErrorReceived事件实现事件处理程序是慢性的,所以你不能说这些数据被损坏了。只问一个问题。 –

+0

您是否建议文章没有任何真正的优点,或者我已经“半化”了代码?如果是后者,那么是的,我并不是指完成的项目,但即使是微软自己也在MSDN上提到,DataReceived事件不会针对每个接收到的字节而提出,而这正是我正在经历的。我链接的文章指出,SerialPort类没有正确使用底层的Win32串口API,所以我只是尝试了一些不同的实验。 –

+0

@HansPassant:你是对的,忽略错误并不是一个好主意,但是'ErrorReceived'事件并不是一个好办法,因为错误情况下成功收到的数据会失序。 (我已经阅读了源代码,IOPSP代码确实具有不可逾越的设计缺陷,这不仅仅基于实验数据)您是否忽视了由'ReadAsync'返回的任务,我推荐也通过完成故障状态? –

回答

2

这是一个递归函数,因此您只需在打开端口后调用此代码,并且它会继续重复自己而不会阻止执行(或需要DataReceived事件处理程序)。

+0

感谢您的回答,我已经对递归代码做了一些阅读,我想我和你在一起。我会在星期一做一些测试,然后我会用一个或两个问题将其标记为答案或评论;)再次感谢。 –

+0

我不知道谁低估了这一点,但穆尔斯是正确的(+1)。我应该知道,我是该博客的作者。 –

+0

另请注意,它不是* true *递归,'BeginRead'块是从完成处理程序调用的,而不是从它本身调用的,所以调用堆栈不会无限增长。 –