问题
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 utilize Invoke. 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
SynchronizationContextreturned bySynchronizationContextrather 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 a Threading.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
回答1:
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
SynchronizationContextobject is created upon creation of the first control in that thread. Before that, it is not defined. - The
SynchronizationContextfor the UI thread is not an instance of theSynchronizationContextclass, but of theSystem.Windows.Forms.WindowsFormsSynchronizationContextclass which is derived fromSynchronizationContext. It is this class that defines the behavior ofPost/Sendallowing marshaling of code from one thread to another. - An appeal of passing the UI thread's
SynchronizationContextaround rather than usingInvokeis that you don't have to keep a reference to your UI form in logic in order to invoke it. - The
Postmethod 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.Senddoesn'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's Invoke/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's SynchronizationContext.
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. :/
来源:https://stackoverflow.com/questions/4998734/vb-net-two-different-approaches-to-generic-cross-threaded-operations-which-is-b