在窗体上调用Control与Invoke

时间:2018-03-21 16:09:21

标签: c# multithreading ui-thread

例如,我使用以下代码:

private void startCalculcationButton_Click(object sender, EventArgs e) {
    int number;
    if (int.TryParse(this.numberTextBox.Text, out number)) {
    this.calculationResultLabel.Text = "(computing)";
        Task.Factory.StartNew(() => {
            int result = LongCalculation(number);
            this.calculationResultLabel.BeginInvoke(new ThreadStart(() => {
                this.calculationResultLabel.Text = result.ToString();
            }));
        });
    }
}

我呼叫this.calculationResultLabel.BeginInvoke(...)切换到UI-Thread,将结果设置为标签。

我也可以使用this.Invoke(...)(这是表格)。它在内部是否有所作为?

1 个答案:

答案 0 :(得分:1)

  

在窗体上调用Control vs. Invoke

     

我也可以使用this.Invoke(...)(这是表格)。它在内部是否有所作为?

听起来你在问两件不同的事情。您的标题为Invoke ,但您的代码正在使用BeginInvoke,但您似乎也在询问是否要在表单或控件上调用。

  1. 对于表单或特定控件,xxxInvoke是否没有区别。两者都是UI元素,两者都可以为你编组电话。

  2. 如果您询问InvokeBeginInvoke之间的区别,可以通过消息泵封送对UI线程的调用的两种方法,它们之间存在差异。 Invoke可能会导致线程死锁,而后者不会。

  3. 无论如何,既然您正在使用Task并且在长时间运行的任务之后立即更新了UI,那么您可以做得更好:

    private void startCalculcationButton_Click(object sender, EventArgs e) {
        int number;
        if (int.TryParse(this.numberTextBox.Text, out number)) 
        {
            this.calculationResultLabel.Text = "(computing)"; // UI thread
            var result  = await Task.Run(() => 
                    LongCalculation(number));  // threadpool thread
    
            calculationResultLabel.Text = result.ToString(); // UI thread
        }
    }
    

    通过BeginInvoke或危险使用Invoke无需手动编组。