如何调用组件

时间:2014-07-18 09:20:29

标签: c# backgroundworker invoke

在我的应用程序中,我使用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

2 个答案:

答案 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;
        }
    }