开发者

VB.NET Two different approaches to generic cross-threaded operations; which is better?

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 SynchronizationContext returned by SynchronizationContext 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 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
En开发者_运维技巧d 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 the SynchronizationContext class, but of the System.Windows.Forms.WindowsFormsSynchronizationContext class which is derived from SynchronizationContext. It is this class that defines the behavior of Post/Send allowing marshaling of code from one thread to another.
  • An appeal of passing the UI thread's SynchronizationContext around rather than using Invoke 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'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. :/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜