我应该使用 Invoke 或 SynchronizationContext 从另一个线程更新表单控件吗?
尝试从其他线程更新 UI 控件。
目前正在使用 BeginInvoke,老实说它工作正常,但我不断听说如何使用 SynchronizationContext 来完成同样的事情。
哪个是首选?
另外,从线程更新 UI 是不好的做法吗?引发事件并让主窗体处理它会更好吗?还是还有其他更好的方法来做到这一点?
很抱歉这个有点主观的问题,但是线程世界中有很多选择,我试图掌握它们的差异以及它们各自的适用范围,以及为未来编写可读和可扩展代码的最佳实践。
编辑:现在我还看到还有 TaskScheduler.FromCurrentSynchronizationContext
路线..这么多选择 x_x
Trying to wrap my head around updating UI controls from other threads.
Currently using BeginInvoke and honestly it's working fine but I keep hearing about how you can use SynchronizationContext as well to do the same thing.
Which is preferred?
Also, is it bad practice to update the UI from a thread? Would it be better to raise an event and have the main form handle it instead or are there other preferable ways to do that as well?
Sorry for the somewhat subjective question but there are so many options in the world of threading and I'm trying to grasp their differences and where each of them are applicable, along with best practices for writing readable and extendable code for the future.
Edit: Also now I see there is the TaskScheduler.FromCurrentSynchronizationContext
route as well.. So many choices x_x
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我更喜欢
SynchronizationContext
而不是Control.Invoke
。Control.Invoke
的危险在于拥有的Control
存在生命周期问题。如果在您尝试Invoke
时控制被释放,那么它会影响调用成功的能力。当对话框关闭、视图移动等时会发生这种情况...SynchronizationContext.Current
不过通常与它关联的线程一样存在。它确实有有限的生命周期,因此最终会出现相同的问题,但它比Control
更可预测。I prefer
SynchronizationContext
overControl.Invoke
. The danger ofControl.Invoke
is that there is a lifetime issue with the owningControl
. If the Control is disposed while you are trying toInvoke
on it then it compromises the ability of the call to succeed. This happens when dialogs are closed, views shifted, etc ...SynchronizationContext.Current
though generally lives as long as the thread it's associated with. It does have a finite lifetime and hence ultimately the same problems but it's a bit more predictable than aControl
.您是否考虑过使用后台工作组件?对于不应该占用 UI 的长时间运行的任务,这是一种获得多线程功能的干净而简单的方法。例如,您可以使用 ProgressChanged 事件和后台工作程序对 UI 执行更新,并且后台工作程序类将确保创建 BW 的线程是执行 ProcessChanged 和 WorkComplete 事件的线程。因此,如果您从 UI 制作了 BW 并使其开始工作,那么您可以从那里安全地更新 UI。
这是 MS 的一篇简短文章
http://msdn.microsoft.com/en -us/library/cc221403%28v=vs.95%29.aspx
另一个非常好的链接
http://www.albahari.com/threading/part3.aspx#_BackgroundWorker
Have you looked into using a Background Worker component? For long running tasks that shouldn't tie up the UI it is a clean and easy way to get multithreading capabilites. For instance you can perform updates to the UI using the ProgressChanged Event and the background worker and the background worker class will ensure that the thread that created the BW is the one that executes the ProcessChanged and WorkComplete event. So if you made the BW from the UI and set it off to work then you can update the UI safely from there.
Here's a quick article from MS
http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx
Another really good link
http://www.albahari.com/threading/part3.aspx#_BackgroundWorker