我应该如何从串行端口数据触发的C#事件更新我的UI

本文关键字:事件 更新 UI 我的 串行端口 数据 我应该 | 更新日期: 2023-09-27 18:24:27

我是一名技术级别的员工,在制造测试环境中帮助进行一些编码。具体的问题是在C#中处理事件。不仅仅是Button_click,特别是如果我有一个通过串行端口的数据流,并且必须根据通过串行端口输入的内容实时更新UI。例如,如果我有两种方法最终都做相同的事情,那么它们之间的区别是什么:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    input = (sender as SerialPort).ReadLine();
    if (input.Contains("look for this"))
        this.Invoke(new EventHandler(doSomething));
}

类似于:

void OnGotData(object sender, EventArgs e) {...};
delegate void UpdateCallback(data d);
void doSomething(data d) {
   ...
  if (field.InvokeRequired) {
            UpdateCallback x = doSomething;
            this.Invoke(x, new object[] { d });
  }
  else {
            field.Text = d;
  }
   ...
}

权衡是什么?更复杂的第二种方法是惯例吗?当实时性能很重要时,我可以在任何地方使用第一种方法吗?

我应该如何从串行端口数据触发的C#事件更新我的UI

如果我理解:第一种方法-始终调用invoke来更新UI第二种方法——如果InvokeRequired返回true调用invoke-else——只做UI内容

现在,如果我们知道控制的句柄已经创建,并且我们只想进行小而快速的UI更新,我们可以使用第一种方法,UI将负责,但使用Invoke死锁仍然是可能的。如果我们现在不这样做,如果控件的句柄已经创建,我们必须调用IsHandleCreated以确保Invoke将成功并且不会引发异常。如果IsHandleCreated返回false,则无法通过Invoke进行更新,必须等待句柄被创建。

第二种方法更糟,因为领域。如果没有创建控件的句柄,InvokeRequired可能会返回false,并且当我们调用field.Text = d;时,控件的句柄可能会在后台线程上创建,从而在没有消息泵的线程上隔离控件,并使应用程序不稳定。

所以对我来说,这是更好的方式:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    input = (sender as SerialPort).ReadLine();
    if (input.Contains("look for this"))
    {   if (this.IsHandleCreated == false)
        {
        //do some stuff to proper handle creation or just wait for handle creation
        }
        this.BeginInvoke(new EventHandler(doSomething));
    }
}