【问题标题】:Will SerialPort DataReceived Event trigger repeatedly?SerialPort DataReceived 事件会重复触发吗?
【发布时间】:2010-05-16 18:25:05
【问题描述】:

假设只要有 100 个字节可用,我就从 SerialPort 读取数据,否则什么都不做。这意味着,剩余的数据仍将在 SerialPort 缓冲区中可用。此读取在 DataReceived 的事件处理程序中完成。

现在假设出现一种情况,即 SerilaPort 缓冲区中有 50 个字节,但没有更多数据进来。据我了解,只要有一定数量的字节可用于从缓冲区读取,就会触发 DataReceived 事件。

现在,在给定的场景中,如果我从不读取这 50 个字节,是否会因为这些未读取字节的存在而连续激活事件?

【问题讨论】:

  • 我怀疑您使用的是 .Net 2.0 SerialPort 对象。您期望如何触发 DataReceived 事件?通过 SerialPort.ReadTimeout?通过 SerialPort.PinChanged?
  • 我使用的是.NET 3.5,但我猜内部实现与2.0版本相同。我所做的只是使用委托 SerialDataReceivedEventHandler 向 DataReceived 事件注册一个函数。
  • 没有。从文档“当从 SerialPort 对象接收到数据时,在辅助线程上引发 DataReceived 事件。”阅读此social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/…

标签: c# events serial-port buffer


【解决方案1】:

我确实发布了答案(参见上面的 cmets)。它在文档中。 “......当从 SerialPort 对象接收到数据时。” OP 说“如果我从不读取这 50 个字节,是否会由于这些未读字节的存在而连续激活事件?”你回答“是的,它会一直触发直到你调用 Read()。”

该事件仅在收到新数据时触发。如果您不处理那条数据,那条数据将不会导致新事件。但是,如果有新数据到达,则会触发一个新事件,然后您可以对其进行处理。

【讨论】:

  • "为了消除所有混乱,您总是读取事件中的 BytesToRead 的数量,读取更少是没有意义的。这意味着当事件再次触发时,您会获得新的字节。"那是你的意见。如果在事件中读取字节时有更多字节到达,会发生什么?我在 0.75 Mbps 下进行的测试表明确实发生了。
  • 好的,谢谢你们的帮助 :) 但是请让我们更专业一点。我们可以努力证明我们的观点或反驳别人的观点,但发动一场激烈的战争并不是一件很酷的事情。
【解决方案2】:

是的,当额外的字节进来时,它会一直触发,直到你调用 Read()。您可以使用 ReceivedBytesThreshold 属性来延迟它。这通常是个坏主意,由于溢出错误而丢失一个字节可能会导致通信完全中断。自己在事件处理程序中缓冲您 Read() 的内容。

另外请注意,这只是 Microsoft 串行端口驱动程序的已知行为。 SerialPort 类使用 WaitCommEvent API 函数,由驱动程序来实现。尤其是大量模拟串行端口以轻松连接到自定义设备的 USB 驱动程序,这并不是平等的。

【讨论】:

  • 好的。所以要跟踪新数据的到达,我必须通过其他方式而不是依靠被触发的事件来指示新数据?
  • 呃,不,它会在有新字节可供读取时触发。新鲜的。它们只会在您不阅读时变得陈旧。
  • 但这与您之前的回答不矛盾吗?也许我误解了..你所说的“变陈旧”是什么意思?
  • 我不这么认为。为了消除所有混乱,您总是读取事件中 BytesToRead 的数量,少读没有意义。这意味着当事件再次触发时,您将获得 新鲜 个字节。
  • @dbasnett:来吧伙计,如果您知道正确的答案,那么您应该发布它。您的“这个答案来自另一个高比率的答案,因此一定是错误的”分析”是有漏洞的,没有任何地方说没有数据时事件会触发。不要成为一个拒绝投票的人,发帖。
【解决方案3】:

我认为这证明了我的观点,对不起 VB 代码。

Private Sub Button1_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) _
                          Handles Button1.Click
    'set up the com port for a test
    SerialPort1.PortName = "COM5" 'attached to breakout box with loopback
    SerialPort1.BaudRate = 115200 'some speed
    SerialPort1.Encoding = System.Text.Encoding.GetEncoding("windows-1252")
    Dim b() As Byte = New Byte() {42, 16, 20, 254, 255, 128} 'test data

    ctrcv = 0 'counter
    SerialPort1.Open() 'open the port
    Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff")) 'show time
    SerialPort1.Write(b, 0, b.Length) 'write the test data

    'give the DataReceived event handler chances to fire
    Threading.Thread.Sleep(30000)

    'show the last time it fired and how many times
    Debug.WriteLine(lastRCV.ToString("HH:mm:ss.ffff") & " " & ctrcv)
    'show how many are available to read
    Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff") & " " & SerialPort1.BytesToRead)
    Array.Clear(b, 0, b.Length)
    SerialPort1.Read(b, 0, SerialPort1.BytesToRead) 'read them

    SerialPort1.Close() 'close the port
    Stop
End Sub
Dim ctrcv As Integer = 0, lastRCV As DateTime
Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, _
                                     ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
                                     Handles SerialPort1.DataReceived
    ctrcv += 1
    lastRCV = DateTime.Now
End Sub

调试输出

 09:34:11.3241 <- when the test started
 09:34:11.3642 3 <- the last data received event!, and how many events
 09:34:41.3718 6 <- when the test ended

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    相关资源
    最近更新 更多