VB.NET通用交叉线程操作的两种不同方法;哪个更好? [英] VB.NET Two different approaches to generic cross-threaded operations; which is better?
问题描述
你好,
我最近读了关于使用 SynchronizationContext
对象来控制某些代码的执行线程。我一直在使用泛型子例程来处理(可能)跨线程调用,例如更新使用 Invoke
的UI控件。我是一个业余爱好者,很难理解任何特定方法的优缺点。我正在寻找一些有关哪种方法可能更可取的见解,以及为什么。
Control.InvokeRequired
。
更好的解决方案是使用
SynchronizationContext
返回的
SynchronizationContext
,而不是
控件,线程编组。
另外,当我环顾四周时,为什么大多数关于这类问题SO建议 Invoke
方法,而不提及此方法。
方法1:
Public Sub InvokeControl(Of T As Control)(ByVal Control As T,ByVal Action A (Action)(Of T))
If Control.InvokeRequired Then
Control.Invoke(New Action(Of T,Action(Of T))(AddressOf InvokeControl),New Object(){Control,Action} )
其他
动作(控制)
结束如果
结束小组
方法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
是一个 Threading.SynchronizationContext
对象定义在我的UI窗体的构造函数中(我将它存储在模块中......不知道这是否是最佳选择):
Public Sub New()
InitializeComponent()
SyncContext = WindowsFormsSynchronizationContext.Current
End Sub
然后,如果我想更新控件(例如, Label1
)o在UI表单中,我会这样做:
$ p $ InvokeControl(Label1,Sub(x)x.Text =hello)
或
UIAction(Label1,Sub(x)x.Text =hello)
你们都在想什么?一种方式是首选还是取决于上下文?如果您有时间,请详细了解详细情况!
预先感谢,
Brian
嗯,我一直在做一些阅读,因为我没有得到任何答复,我想我会开始对自己的问题的部分回答,至今已发现:
我发现了一个有趣的codeproject文章讨论使用 SynchronizationContext
来封送线程之间的代码(特别是从工作线程到UI线程)。我发现一些有趣的观察结果:
- UI线程的
SynchronizationContext
对象在创建时创建该线程中的第一个控件。 - UI线程的
SynchronizationContext
不是的实例, SynchronizationContext 类,但是
类的
。正是这个类定义了System.Windows.Forms.WindowsFormsSynchronizationContext
类同步上下文Post
/Send
的行为,允许将代码从一个线程编组到另一个线程。 - 传递UI线程的
SynchronizationContext
而不是使用Invoke
您不必为了调用而在逻辑中保留对UI表单的引用。 -
Post 方法似乎很吸引人因为它是非阻塞的,所以可以完成像指标更新这样的事情,但正如文章指出的那样,发布代码中抛出的异常在UI线程中抛出。即发布到UI的代码中的错误可能会导致UI崩溃。 发送
没有这个问题。
更新:这是<一篇关于使用SynchronizationContext的MSDN文章>另一篇有见解的文章一>。在本文中,Kael Rowan讨论了使用
SynchronizationContext
可能优于控件实例的Invoke
/BeginInvoke
方法。他认为,在编写可重用的库时,仅仅为了调用目的而不得不维持对库之外的控件的引用。他为委托提供代码,以确保创建的任何新线程将共享UI线程的SynchronizationContext
。
好的,好吧,看起来我不会在这里得到更多的评论。我在这里写的是关于我的无知让我得到答案。如果任何人有其他补充,我一定会感激,但我现在继续前进。 :/
VB.NET 2010, .NET 4
Hello,
I recently read about using
SynchronizationContext
objects to control the execution thread for some code. I have been using a generic subroutine to handle (possibly) cross-thread calls for things like updating UI controls that utilizeInvoke
. I'm an amateur and have a hard time understanding the pros and cons of any particular approach. I am looking for some insight on which approach might be preferable and why.Update: This question is motivated, in part, by statements such as the following from the MSDN page on
Control.InvokeRequired
.An even better solution is to use the
SynchronizationContext
returned bySynchronizationContext
rather than a control for cross-thread marshaling.And also, general confusion as to why, as I look around, a majority of answers to questions regarding this type of problem on SO suggest the
Invoke
approach without mentioning this method.Method 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
Method 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
Where
SyncContext
is aThreading.SynchronizationContext
object defined in the constructor of my UI form (I store it in a module... Not sure if that's the best choice):Public Sub New() InitializeComponent() SyncContext = WindowsFormsSynchronizationContext.Current End Sub
Then, if I wanted to update a control (e.g.,
Label1
) on the UI form, I would do:InvokeControl(Label1, Sub(x) x.Text = "hello")
or
UIAction(Label1, Sub(x) x.Text = "hello")
So, what do y'all think? Is one way preferred or does it depend on the context? If you have the time, verbosity would be appreciated!
Thanks in advance,
Brian解决方案Well, I've been doing some reading and, since I'm not getting any responses, I figured I'd start a partial answer to my own question containing what I've found so far:
I found an interesting codeproject article discussing the use of
SynchronizationContext
for marshaling code between threads (and specifically from worker threads to the UI thread). Some observations I found interesting:- The UI thread's
SynchronizationContext
object is created upon creation of the first control in that thread. Before that, it is not defined. - The
SynchronizationContext
for the UI thread is not an instance of theSynchronizationContext
class, but of theSystem.Windows.Forms.WindowsFormsSynchronizationContext
class which is derived fromSynchronizationContext
. It is this class that defines the behavior ofPost
/Send
allowing marshaling of code from one thread to another. - An appeal of passing the UI thread's
SynchronizationContext
around rather than usingInvoke
is that you don't have to keep a reference to your UI form in logic in order to invoke it. - The
Post
method seems appealing for accomplishing things like indicator updates since it's non-blocking, but, as the article points out, exceptions thrown in posted code are thrown in the UI thread. i.e., a bug in code posted to the UI can crash the UI.Send
doesn't have this problem. Exceptions thrown when sending are thrown in the work thread.
Update: Here is another insightful article. In this article, Kael Rowan discusses a context in which using
SynchronizationContext
might be preferable to a control instance'sInvoke
/BeginInvoke
methods. He argues that, when writing a reusable library, it is not desirable to have to maintain a reference to a control outside of the library simply for invokation purposes. He provides code for a delegate that ensures any new thread created will share the UI thread'sSynchronizationContext
.Alright, well, it looks like I'm not going to get any more comments here. What I've written here is about as close as my ignorance allows me to get to an answer. If anyone has anything else to add, I'd surely appreciate it, but I'm moving on for now. :/
这篇关于VB.NET通用交叉线程操作的两种不同方法;哪个更好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- The UI thread's