6

我已经做了一些研究,但我真的找不到从 C# 中的工作线程更新表单控件的首选方法。我知道 BackgroundWorker 组件,但是不使用 BackgroundWorker 组件的最佳方法是什么?

4

4 回答 4

10

有一条一般的经验法则是说不要从 UI 线程本身以外的任何线程更新 UI。使用 BackgroundWorker 的功能是个好主意,但您不想这样做,并且在不同的线程上发生了一些事情,您应该执行“Invoke”或 BeginInvoke 以强制委托在 UI 线程上执行该方法。

编辑:Jon B 在评论中提出了这一点:

请记住,Invoke() 是同步的,而 BeginInvoke() 是异步的。如果使用 Invoke(),则必须小心不要导致死锁。我会推荐 BeginInvoke() 除非你真的需要同步调用。

一些简单的示例代码:

// Updates the textbox text.
private void UpdateText(string text)
{
  // Set the textbox text.
  m_TextBox.Text = text;
}

public delegate void UpdateTextCallback(string text);

// Then from your thread you can call this...
m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText),
    new object[]{"Text generated on non-UI thread."});

上面的代码来自一个关于它的常见问题解答这里和一个更长的涉及更多的一个这里

于 2008-10-15T23:24:09.300 回答
5

你为什么不想使用 BackgroundWorker 来做呢?它有一个很棒的回调事件,叫做 ProgressChanged,它让 UI 线程知道更新,非常适合进度条类型的更新等。

链接到详细信息

于 2008-10-15T23:16:11.470 回答
1

有一个与此相关的讨论这里和一个这里

本质上,您使用 Invoke 来完成它。

祝你好运!

于 2008-10-15T23:18:11.590 回答
1

调用 Invoke 时,我也会考虑 InvokeRequired(仅限 VS2008)。有时您不会从单独的线程更新 UI。它节省了创建委托等的开销。

if (InvokeRequired)
        {
            //This.Invoke added to circumvent cross threading exceptions.
            this.Invoke(new UpdateProgressBarHandler(UpdateProgressBar), new object[] { progressPercentage });
        }
        else
        {
            UpdateProgressBar(progressPercentage);
        }
于 2008-10-16T00:16:14.970 回答