【问题标题】:Should I use Invoke or SynchronizationContext to update form controls from another thread?我应该使用 Invoke 或 SynchronizationContext 从另一个线程更新表单控件吗?
【发布时间】:2011-09-20 05:01:43
【问题描述】:

试图从其他线程更新 UI 控件。

目前正在使用 BeginInvoke,老实说,它工作正常,但我不断听到您如何使用 SynchronizationContext 来做同样的事情。

哪个是首选?

另外,从线程更新 UI 是不好的做法吗?引发一个事件并让主窗体处理它会更好,还是还有其他更好的方法可以做到这一点?

抱歉,这个问题有点主观,但线程领域有很多选择,我试图了解它们的差异以及它们各自适用的地方,以及为未来编写可读和可扩展代码的最佳实践.

编辑:现在我也看到了TaskScheduler.FromCurrentSynchronizationContext 路线。有很多选择x_x

【问题讨论】:

  • 您通常应该支持线程中更高级别的抽象,以帮助自己陷入成功的陷阱。获得正确的线程是困难的。喜欢 Task 或 BackgroundWorker。

标签: c# multithreading invoke


【解决方案1】:

比起Control.Invoke,我更喜欢SynchronizationContextControl.Invoke 的危险在于,拥有 Control 存在终身问题。如果在您尝试对其进行Invoke 处理时释放了控件,那么它会损害调用成功的能力。当对话框关闭、视图转移等时会发生这种情况......

SynchronizationContext.Current 虽然通常与它关联的线程一样长。它确实有一个有限的生命周期,因此最终会出现同样的问题,但它比Control 更容易预测。

【讨论】:

  • 我不认为这句话是正确的“如果在您尝试调用控件时释放了控件,那么它会损害调用成功的能力......”因为实际上是 WindowsFormsSynchronizationContext是 SynchronizationContext 的具体实现,完全使用 Control.Invoke 进行编组Control control = this.controlToSendTo; object[] objArray = new object[] { state }; control.Invoke(d, objArray);,我想说我更喜欢 SynchronizationContext 只是因为它是一种抽象,如果微软更改具体实现,您不必更改代码
  • @MichaelDenny,controlToSendToSyncContext 维护,并且与线程具有相同的生命周期,因此不会被释放,而Control.Invoke 的控制可能已经被释放表单关闭时的示例
【解决方案2】:

您是否考虑过使用 Background Worker 组件?对于不应该占用 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

【讨论】:

  • 我对 BackgroundWorker 很熟悉,但这个项目是针对服务器应用程序的,所以我相信 Tasks/ThreadPool 更适合这个。否则你是对的。可能应该将其包含在原始帖子中。我很抱歉。
  • @John 为什么在服务器应用程序上有 UI 控件?
  • 第二次阅读这个问题后,我想约翰在这里问了两个问题。一是使用同步,二是在 UI 中处理多线程的最佳方式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 2011-01-15
  • 2013-07-10
  • 2013-02-09
  • 1970-01-01
相关资源
最近更新 更多