Simon Farshid
Simon Farshid

Reputation: 2696

SynchronizationContext is null in winforms

I'm creating a library which relies on capturing the SynchronizationContext in order to post callbacks back to the UI thread.

A user was having a weird condition where the callbacks were being posted to the ThreadPool instead. After investigating a bit, I came up with the following two test cases:

1:

public partial class Form1 : Form
{
    private Test test;

    public Form1()
    {
        test = new Test();
        InitializeComponent();
    }

    private class Test
    {
        public Test()
        {
            if (SynchronizationContext.Current == null)
                throw new InvalidOperationException("It's null! :(");
        }
    }
}

2:

public partial class Form1 : Form
{
    private Test test = new Test();

    public Form1()
    {
        InitializeComponent();
    }

    private class Test
    {
        public Test()
        {
            if (SynchronizationContext.Current == null)
                throw new InvalidOperationException("It's null! :(");
        }
    }
}

The 1st test runs fine, but the 2nd one throws an exception. Why?

Upvotes: 2

Views: 137

Answers (1)

usr
usr

Reputation: 171246

In the second example new Test() runs (almost) as the very first code in the program. Probably, your Main function calls new Form1() which immediately calls new Test().

A SynchronizationContext must be set before it is present (obviously). There is nothing magic in the runtime that guesses that your app will use WinForms. Using WinForms is a dynamic runtime decision. WinForms will set its SynchronizationContext when you use WinForms (I forgot the exact trigger points).

In the first example the base constructor (new Form()) runs first which apparently installs the SynchronizationContext.

When you run code before any WinForms code runs no SynchronizationContext will/can be present.

There is nothing sane that your library can do about this. You could add an assert or manually set the WinForms sync context (there is a API for that) but that is hardly the business of a library. Libraries are not supposed to mess with global state. (Except if your library is clearly meant for WinForms-only use).

Upvotes: 2

Related Questions