你好,
我最近阅读了有关使用SynchronizationContext对象来控制某些代码的执行线程的内容.我一直在使用通用子例程来处理(可能)跨线程调用,例如更新利用Invoke的UI控件.我是一名业余爱好者,很难理解任何特定方法的优缺点.我正在寻找一些有关哪种方法可能更可行以及为什么更有用的见解.
更新:这个问题的动机部分来自于MSDN page on Control.InvokeRequired
中的以下陈述.
An even better solution is to use the
SynchronizationContext
returned by
SynchronizationContext
rather than a
control for cross-thread marshaling.
而且,在我看来,为什么在SO上关于这类问题的大多数问题的答案都提出了Invoke方法,而没有提到这种方法.
方法1:
Public Sub InvokeControl(Of T As Control)(ByVal Control As T,ByVal Action As Action(Of T)) If Control.Invokerequired Then Control.Invoke(New Action(Of T,Action(Of T))(AddressOf InvokeControl),New Object() {Control,Action}) Else Action(Control) End If End Sub
方法2:
Public Sub UIAction(Of T As Control)(ByVal Control As T,ByVal Action As Action(Of Control)) SyncContext.Send(New Threading.SendOrPostCallback(Sub() Action(Control)),Nothing) End Sub
其中SyncContext是在我的UI表单的构造函数中定义的Threading.SynchronizationContext对象(我将其存储在模块中……不确定这是否是最佳选择):
Public Sub New() InitializeComponent() SyncContext = WindowsFormsSynchronizationContext.Current End Sub
然后,如果我想更新UI表单上的控件(例如,Label1),我会这样做:
InvokeControl(Label1,Sub(x) x.Text = "hello")
要么
UIAction(Label1,Sub(x) x.Text = "hello")
那么,你们都在想什么呢?是一种首选方式还是取决于具体情况?如果你有时间,可以感谢详细!
提前致谢,
布赖恩
我发现interesting codeproject article讨论了使用SynchronizationContext在线程之间编组代码(特别是从工作线程到UI线程).我发现一些有趣的观察:
> UI线程的SynchronizationContext对象是在该线程中创建第一个控件时创建的.在此之前,它没有定义.
> UI线程的SynchronizationContext不是SynchronizationContext类的实例,而是从SynchronizationContext派生的System.Windows.Forms.WindowsFormsSynchronizationContext类的实例.正是这个类定义了Post / Send的行为,允许将代码从一个线程编组到另一个线程.
>传递UI线程的SynchronizationContext而不是使用Invoke的吸引力在于您不必在逻辑中保留对UI表单的引用以便调用它.
> Post方法似乎很有必要完成指标更新之类的事情,因为它是非阻塞的,但正如文章所指出的那样,在UI线程中抛出了已发布代码中抛出的异常.即,发布到UI的代码中的错误可能导致UI崩溃.发送没有这个问题.在工作线程中抛出发送时抛出的异常.
更新:这是another insightful article.在本文中,Kael Rowan讨论了一个上下文,其中使用SynchronizationContext可能比控件实例的Invoke / BeginInvoke方法更可取.他认为,在编写可重用的库时,不希望仅为了调用目的而在库外维护对控件的引用.他为委托提供代码,确保创建的任何新线程将共享UI线程的SynchronizationContext.
好吧,好吧,看起来我不会再在这里得到任何评论了.我在这里所写的内容与我的无知能让我得到答案一样接近.如果有人还有其他东西需要补充,我肯定会感激,但我现在还在继续. :/