我偶然发现了专业库中的一些代码,并且不确定这是否是一种处理跨线程事件调用的简洁方法。
以下代码位于表单应用程序中。线程调用是从一个本身启动一个新线程并接收消息的类中进行的:
private void Library_StatusChanged(object sender, AbstractTestCase.StatusChangedEventArgs e)
{
if (this.InvokeRequired)
{
this.lblProgress.Invoke((MethodInvoker)delegate ()
{
lblProgress.Text = "Current state: " + e.Step;
lblProgress.Refresh();
}
);
this.pbProgess.Invoke((MethodInvoker)delegate ()
{
pbProgess.Value = e.Percentage;
pbProgess.Refresh();
});
this.lstStatus.Invoke((MethodInvoker)delegate ()
{
lstStatus.Items.Add(" " + e.Step);
lstStatus.Refresh();
});
this.Invoke((MethodInvoker)delegate ()
{
this.Refresh();
});
}
else
{
lblProgress.Text = "Current state:" + e.Step;
lblProgress.Refresh();
pbProgess.Value = e.Percentage;
pbProgess.Refresh();
lstStatus.Items.Add(" " + e.Step);
lstStatus.Refresh();
this.Refresh();
}
Application.DoEvents();
}
这是“最先进的”吗?在我看来,它有点乱??
答案 0 :(得分:5)
现有技术正在使用await
。如果这不可行,至少将代码简化为单个Invoke
调用。不需要在每个控件上调用,只需在UI线程上的任何位置调用。
不应该要求InvokeRequired
检查,因为您应该知道在哪个线程上引发事件。
在任何情况下,复制"Current state: " + e.Step
之类的逻辑都是一个坏主意,无论如何我都会在代码审查中失败。
Application.DoEvents
的存在是一个非常糟糕的迹象。可能是误解,因为只在UI线程上调用它才有意义,但为什么Invoke
已经在UI线程上了?!看起来像是一个矛盾。
lstStatus.Refresh();
也是一种误解,可能是迷信。控制自动刷新(如果允许事件处理)。
答案 1 :(得分:1)
使用invoke时,会在队列中添加一条语句,以供UI线程处理。
使用这个简单的解决方案:
private void Library_StatusChanged(object sender, AbstractTestCase.StatusChangedEventArgs e)
{
this.lblProgress.Invoke((MethodInvoker)delegate ()
{
lblProgress.Text = "Current state: " + e.Step;
});
this.pbProgess.Invoke((MethodInvoker)delegate ()
{
pbProgess.Value = e.Percentage;
});
this.lstStatus.Invoke((MethodInvoker)delegate ()
{
lstStatus.Items.Add(" " + e.Step);
});
}