我是一名技术级员工,在制造测试环境中帮助完成一些编码工作。具体问题是在 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;
}
...
}
权衡是什么?更复杂的第二种方法是否是约定俗成的问题,当实时性能很重要时,我可以在任何地方使用第一种方法吗?
最佳答案
如果我理解: 第一种方法——总是调用 invoke 来更新 UI 第二种方法 - 如果 InvokeRequired 返回 true 调用调用 else - 只做 UI 的事情
现在,如果我们知道控件的句柄已创建并且我们只想进行小而快速的 UI 更新,我们可以使用第一种方法,UI 将负责,但使用 Invoke 死锁仍然是可能的。如果我们现在不创建控件句柄,则我们必须调用 IsHandleCreated 以确保 Invoke 成功并且不会抛出异常。如果 IsHandleCreated 返回 false,我们无法通过 Invoke 更新,我们必须等待句柄创建。
第二种方法更糟糕,因为如果未创建控件句柄,则 field.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));
}
}
关于c# - 我应该如何从串行端口数据触发的 C# 事件更新我的 UI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17800842/