What is SynchronizationContext in .NET

  • multi threaded programs usually uses one of the threads as means of synchronization
  • there are message loops to pass unit of works (like Windows message queue)
  • message queues require messages formats and convention for handling it
  • single thread to handle ASP.NET request is waste of the resources (before .NET 2)
  • thread pool was better but inconvenient to work with
  • instead SynchronizationContext queues work for given context not thread
  • thread have current context
  • context does not have to be unique but can be shared between multiple threads
  • thread can change context but this is rare
  • SynchronizationContext keeps count of all asynchronous operations
  • Windows Forms uses WindowsFormsSynchronizationContext
  • WPF and Silverlight uses DispatcherSynchronizationContext
  • Console app and WindowsServices and ThreadPool threads uses default SynchronizationContext
  • ASP.NET uses AspNetSynchronizationContext

Further read:

https://learn.microsoft.com/pl-pl/archive/msdn-magazine/2011/february/msdn-magazine-parallel-computing-it-s-all-about-the-synchronizationcontext

Does async/await creates new thread?

In short: no.

Longer explanation:

  • task that want to do I/O write call to driver write
  • driver operations are performed asynchronously
  • write operations on devices is done without CPU involved
  • finish of writing is done via interrupt
  • interrupt, schedules Deferred Procedure Call
  • DPC schedules Asynchronous Procedure Call
  • APC notifies thread that I/O write is done
  • task that was doing I/O is scheduled with continuation of its method after I/O is done.
  • some threads might need to be borrowed for handling APC and such but no thread is spawn to handle I/O

I recommend reading this post: https://blog.stephencleary.com/2013/11/there-is-no-thread.html. This will explain the topic much better than I can.

Further read:

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model#BKMK_Threads

Asynchronous programming in .NET

Asynchronous programming patterns in .NET:

Ways of achieving asynchronous code in .NET

  • async, await
  • Task class API (Run, WhenAll, WhenAny, etc.)
  • ThreadPool.QueueUserWorkItem(ThreadProc);

Further read:

async/await in .NET

https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/

async/await in C#

async/await syntax should be used for I/O bound asynchronous operations only.

public async Task<int> GetUrlContentLengthAsync()
{
    var client = new HttpClient();

    Task<string> getStringTask =
        client.GetStringAsync("https://docs.microsoft.com/dotnet");

    DoIndependentWork();

    string contents = await getStringTask;

    return contents.Length;
}

Compiler transforms code into a state machine that to track yielding execution for await and resuming execution when a background job is finished.

Things to keep in mind:

  • async method needs await
  • add Async suffix to asynchronous methods
  • async void for ‘Fire and Forget’ work i.e. event Handlers
  • be aware of mixing LINQ with async lambdas
  • wait for tasks in a non-blocking manner (do not use Task.Result i.e.)
  • for tight loops use ValueTasks
  • Consider using ConfigureAwait(false) for performance and for avoiding deadlocks

Further read:

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model