I’ve been using SynchronizationContext for quite a while now. To me it is the best way to synchronize with the main thread. If you do a lot of winforms development like I do than you will know that you need to do this a lot. Blocking the UI is a nono.

SynchronizationContext has 2 methods that are of interest to us. Send and Post. According to the MSDN documentation. 

  • Post: When overridden in a derived class, dispatches an asynchronous message to a synchronization context.
  • Send: When overridden in a derived class, dispatches a synchronous message to a synchronization context.

Meaning that Post is Async and Send is Synch. In most cases you won’t notice much difference between the two. And in most cases I would just recommend Post. Since in most cases you are just using the Synchronizationcontext to show something on the screen. I will however show you when Send is the better choice. And that is when you need to read from a control and need that result for later processing. This is a very simplified case but it makes the point quite nicely.

Lets make a form like this.

 

Empty form with 3 textboxes and a button

Empty form with 3 textboxes and a button

And now add this code.

Imports System.Threading

Public Class Form1

    Private _synchro As SynchronizationContext

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        _synchro = SynchronizationContext.Current
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Task.Run(Sub()
                     DoMath(TextBox2, GetNumberSync)
                     DoMath(TextBox3, GetNumberASync)
                 End Sub)
    End Sub

    Private Function GetNumberSync() As Integer
        Dim returnvalue As Integer
        _synchro.Send(Sub()
                          returnvalue = Convert.ToInt32(TextBox1.Text)
                      End Sub, Nothing)
        Return returnvalue
    End Function

    Private Function GetNumberASync() As Integer
        Dim returnvalue As Integer
        _synchro.Post(Sub()
                          returnvalue = Convert.ToInt32(TextBox1.Text)
                      End Sub, Nothing)
        Return returnvalue
    End Function

    Private Sub DoMath(ByVal control As Control, ByVal x As Integer)
        _synchro.Post(Sub()
                          control.Text = (x + 1).ToString
                      End Sub, x)
    End Sub


End Class

The result will be this.

Synch2

So for the send method this is 2 because the line with the return will only be executed after the send has completed. For the post method this will be one because the returnvalue gets set sometime in the future which will most likely be after the Return has been called.

So something to be aware of.