C# 从工作线程更新表单控件的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/206867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 18:02:57  来源:igfitidea点击:

What is the best way to update form controls from a worker thread?

c#multithreadingforms

提问by Yttrium

I've done some research and I can't really find a preferred way to do updating of form controls from a worker thread in C#. I know about the BackgroundWorker component, but what is the best way to do it without using the BackgroundWorker component?

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

采纳答案by AR.

There's a general rule of thumb that says don't update the UI from any thread other than the UI thread itself. Using the features of the BackgroundWorker is a good idea, but you don't want to and something is happening on a different thread, you should do an "Invoke" or BeginInvoke to force the delegate to execute the method on the UI thread.

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

Edit: Jon B made this good point in the comments:

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

Keep in mind that Invoke() is synchronous and BeginInvoke() is asynchronous. If you use Invoke(), you have to be careful not to cause a deadlock. I would recommend BeginInvoke() unless you really need the call to be synchronous.

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

Some simple example code:

一些简单的示例代码:

// 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."});

The code above is from a FAQ about it hereand a longer more involved one here.

上面的代码来自关于它的常见问题解答here和一个更复杂的here

回答by Mark

Why dont you want to do it using the BackgroundWorker? It has a fantastic callback event called ProgressChanged which lets the UI thread know about updates, perfect for progess bar-type updates and the like.

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

link to details

链接到详细信息

回答by itsmatt

There's a discussion related to this hereand one here.

有一个与此相关的讨论here和一个here

Essentially, you use Invoke to accomplish it.

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

Best of luck!

祝你好运!

回答by AR.

I would also consider InvokeRequired (VS2008 only) when calling Invoke. There are times that you will not be updating the UI from a seperate thread. It saves the overhead of creating the delegate etc.

在调用 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);
        }