【问题标题】:What happens if event occurs again when the first is not finished handling如果第一个未完成处理时再次发生事件会发生什么
【发布时间】:2018-06-11 12:46:31
【问题描述】:

我的问题是关于来自System.IO.SerialPortDataReceived 事件。我有一个在该事件发生时被调用的方法。我用myPort.ReadExisting 读取数据,处理并保存。如果我得到一个特定字符,那么到该点的数据将被解释为命令并触发另一个事件。

我的问题是,如果我正在处理接收到的数据并且有新数据出现,会发生什么?方法的新实例是否在等待旧实例完成?如果不是,则可能导致冲突,因为该方法的两个实例都使用相同的变量。我在事件处理的概念上是错的还是有一种优雅的方式来处理它。

我的代码运行良好,结果符合预期,但我的数据处理没有那么复杂。我只是想了解这个问题并避免将来遇到问题。 我的代码示例是这样的:

private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

        SerialPort port = (SerialPort)sender;
        int index = m_ports.FindIndex(p => p.PortName == port.PortName);
        string tmpData;
        m_currentData[index] += tmpData = port.ReadExisting();
        Console.WriteLine(tmpData);

        string currentData = m_currentData[index];
        string currentOrder = "";
        while (currentData.Contains(orderEndChar))
        {
            int endCharLocation = currentData.IndexOf(orderEndChar);
            currentOrder = currentData.Substring(0, endCharLocation);
            currentData = currentData.Substring(endCharLocation + 1);
            orderEvent.gotOrder(currentOrder);
            //orderEvent.gotOrder(new EventArgs());
        }
        m_currentData[index] = currentData;

}

这些列表是因为我希望它与多个端口一起工作,我可以从中获取命令。

【问题讨论】:

  • 您可以通过在方法的开头和结尾调用Console.WriteLine 自行测试。
  • 相关帖子。请看看它是否有帮助 - IO operation aborted error thrown while reading serial port
  • 如何为每个传入的数据启动一个新线程,这样就不用等待了?
  • 我不确定我是否完全理解您所关心的问题,但是 I/O 中断不会导致您的程序跳出它所在的任何方法;该事件将在消息循环中排队等待处理。
  • @DamoV 这真是个疯狂的想法。

标签: c# event-handling serial-port


【解决方案1】:

SerialPort.DataReceived 在辅助线程上调用。
在这里阅读: https://msdn.microsoft.com/fi-fi/library/system.io.ports.serialport.datareceived(v=vs.110).aspx

因此,如果您有许多 SerialPort 实例正在侦听,则可能会同时运行多个 Port_DataReceived 方法。但是不要害怕局部变量,因为它们只存在于特定的方法调用中。因此,运行相同方法的 3 个不同线程将启动 3 个不同的局部变量,即使它们的名称相同。但要小心全局变量。

由于Port_DataReceived 是同步的,下一次事件调用在同一个 SerialPort object 将等待,因此这些调用将被一个一个地执行。

【讨论】:

  • 如此同步意味着如果方法仍在运行,则不会从一个对象再次调用该方法。假设 COM1 端口发出数据接收并得到处理,然后新数据到达。 COM1 端口会等待发送 datareceived 事件还是处理程序等待调用该方法?所以数据接收到的事件会以某种方式在内部排队?
  • 是的,排队(如果有的话)是在SerialPort 端内部实现的,或者可能在协议级别更深。
【解决方案2】:

因此,如果您怀疑您的生产者可能比您的消费者运行得更快,您应该通过使用队列将两者解耦。

您的生产者所要做的就是将它接收到的数据推送到一个(线程安全的)队列中......这是一个不会溢出的快速操作。

消费者所要做的就是以自己的速度从队列中读取数据。

TPL Dataflow 提供了BufferBlock<T> 类,它可以作为这种生产者/消费者关系的便捷队列。

您可能会选择更深入地研究数据流。它非常适合异步世界中的生产者/消费者。

从这里开始:https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-messages-to-and-read-messages-from-a-dataflow-block

【讨论】:

    猜你喜欢
    • 2015-12-25
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    相关资源
    最近更新 更多