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
What is the best way to update form controls from a worker thread?
提问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.
回答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 线程知道更新,非常适合进度条类型的更新等。
回答by itsmatt
回答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);
}