Jurass
Jurass

Reputation: 596

C# async await has different behavior for UI

Async await has different behavior in Win Forms and in my Console App. For the given sample code the output will looks like this:

Line 1: 1
Line 2: 1
Line 3: 1
Line 4: 1
Line 5: 1
Insde the Task: 3
After await: 3

But if I will run similar functions in WinForms on_button_click function I will get this result:

 Line 1: 1
 Line 2: 1
 Line 3: 1
 Line 4: 1
 Line 5: 1
 Insde the Task: 3
 After await: 1 // HERE'S THE DIFFERENCE, after await thread 1 will continue instead of thread 3

That difference in WinForms is significant because thanks to this I will not receive Exception for modifying form outside of dispatcher thread. My question is, how can I achieve same behavior in my console application?

 class Program
{
    public async void methodAsync()
    {
        Trace.WriteLine("Line 2: " + currentThread());
        await method();
        Trace.WriteLine("After await: " + currentThread());
    }
    public Task method()
    {
        Trace.WriteLine("Line 3: " + currentThread());

        Task t = new Task(() =>
        {
            Trace.WriteLine("Insde the Task: " + currentThread());

        });

        t.Start();

        Trace.WriteLine("Line 4: " + currentThread());

        return t;
    }
    public string currentThread()
    {
        return System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
    }

    public void test()
    {
        Trace.WriteLine("Line 1: " + currentThread());
        methodAsync();
        Trace.WriteLine("Line 5: " + currentThread());

        System.Threading.Thread.Sleep(2000);
    }
    static void Main(string[] args)
    {
        Program p = new Program();
        p.test();
    }

Upvotes: 0

Views: 81

Answers (1)

Alexei Levenkov
Alexei Levenkov

Reputation: 100527

Console's SynchornizationContext does not switch threads to execute code after async method returns thus you see same id for async part of the method and same thread Id for code after await. WinForms, WPF Synchronization Contexts pick particular (UI) thread to execute code after await to avoid running code that would run on UI thread if code is synchronous on some other thread.

In theory you can create your own SynchronizationContext that will post continuations to whatever thread you like. In practice console's code generally has no problem to run on any thread and hence it is not necessary (unlike in UI cases where code accessing UI elements must run on UI thread).

If you decide to create your own some samples can be found by https://www.bing.com/search?q=c%23+custom+console+synchronizationcontext like Looking for an example of a custom SynchronizationContext (Required for unit testing)

Upvotes: 4

Related Questions