在我的应用程序中,我使用backgroundWorker,在某些TextBox中设置文本,我首先需要调用TextBox。
首先我使用:
if (someTextBox.InvokeRequired)
{
someTextBox.Invoke((MethodInvoker)delegate
{
someTextBox.Text = "some_text";
});
}
else
{
someTextBox.Text = "some_text";
}
这个方法对我很好,但因为我有多个TextBox-es我写道:
private void invComp(TextBox txtBox, String str)
{
if (txtBox.InvokeRequired)
{
txtBox.Invoke((MethodInvoker)delegate
{
txtBox.Text = str;
});
}
else
{
txtBox.Text = str;
}
}
最好以这种方式调用它吗? (invComp(someTextBox," some_text"); 或者也许我有一些第三,更好的方式?
我调用了一些按钮,如果可以的话,我想写按钮来写这样的东西?
TNX
答案 0 :(得分:5)
Control.InvokeRequired遭受货运崇拜。您正在从工作线程更新控件,知道需要调用。所以测试它绝对没有意义。除了一个原因,当它是 false 时,存在根本性的错误。与程序员相比,这种情况发生得更频繁,忘记在用户关闭窗口时停止工作人员是传统的错误。这会导致各种各样的混乱,你想知道它:
private void invComp(TextBox txtBox, String str) {
if (!this.InvokeRequired) throw new InvalidOperationException("You forgot to stop the worker");
this.BeginInvoke(new Action(() => txtBox.Text = str));
}
简短而活泼,失败安全且快速。良好的代码质量。请注意,它使用表单的BeginInvoke()方法,它不依赖于正在创建的子控件。并且它使用BeginInvoke()而不是Invoke(),这对于不会使工作线程陷入困境并避免死锁很重要。始终避免使用Invoke(),只有在需要知道方法返回值时才需要它。
完全不同的做法是使用BackgroundWorker专注于您。它已经调整了对UI线程的调用,只是该方法具有笨拙的名称。您可以获取ProgressChanged事件来执行任何代码,它不足以显示进度。像这样编写你的事件处理程序:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
((Action)e.UserState).Invoke();
}
现在,您可以在UI线程上执行任何代码:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
var worker = (BackgroundWorker)sender;
//...
worker.ReportProgress(0, new Action(() => textBox1.Text = "hello"));
}
答案 1 :(得分:1)
您可以稍微修改您的方法,使其成为通用方法,以便您可以使用if进行任何控制。
private void invComp<T>(T control, String str) where T: Control
{
if (control.InvokeRequired)
{
control.Invoke((MethodInvoker)delegate
{
control.Text = str;
});
}
else
{
control.Text = str;
}
}