Composing async work: WhenAll WhenAny and WhenEach

 
 
  • Gérald Barré
Everything so far has been about a single operation. This post is about running several, which is where async stops being a syntax feature and starts changing what your program does. The mechanics are three combinators and one throttle, and each has an exception behaviour that is worth knowing before you meet it in production. Starting is what makes them concurrent Before the combinators, the thing they… [read more]

SynchronizationContext ConfigureAwait and deadlocks

 
 
  • Gérald Barré
The previous post covered ExecutionContext, which decides what state a continuation sees. This post is about the other thing await captures, which decides where the continuation runs. It is also the mechanism behind the single most famous bug in async C#: calling .Result and hanging forever. What a SynchronizationContext is A SynchronizationContext is an abstraction over "post this callback to the right… [read more]

Async method builders and where the allocations go

 
 
  • Gérald Barré
The post on the compiler rewrite pulled an async method apart and found a generated struct with a MoveNext method. One field in that struct was left unexplained: public AsyncTaskMethodBuilder<int> <>t__builder; The builder is the other half of the machinery. The state machine knows where it is; the builder knows what to hand back to the caller and how to get running again. It is also the piece you can… [read more]

Writing your own CancellationToken from scratch

 
 
  • Gérald Barré
The previous post built a MyTask that can start work and report that it finished. It cannot stop anything. That gap is not an oversight in the implementation: stopping is a separate concern, and .NET models it as a separate pair of types. This post builds those too. MyCancellationTokenSource and MyCancellationToken, from scratch, and then wires them into MyTask. The implementation is short. The design… [read more]