Consider the following example:
async Task DoWork()
{
await Task.Run(() =>
{
for (int i = 0; i < 25; i++)
{
Console.WriteLine("Task run 1: " + Thread.CurrentThread.ManagedThreadId);
}
});
// The SynchronizationContext.Post() gets called after Run 1 and before Run 2
await Task.Run(() =>
{
for (int i = 0; i < 25; i++)
{
Console.WriteLine("Task run 2: " + Thread.CurrentThread.ManagedThreadId);
}
});
// I expect it to run after Run 2 and before Run 3 as well but it doesn't
await Task.Run(() =>
{
for (int i = 0; i < 25; i++)
{
Console.WriteLine("Task run 3: " + Thread.CurrentThread.ManagedThreadId);
}
});
}
I would expect a call to SynchronizationContext.Post() to be made every time an await operation ends but after overriding the Post() like this
public class MySynchronizationContext
{
public override void Post(SendOrPostCallback d, object? state)
{
Console.WriteLine("Continuation: " + Thread.CurrentThread.ManagedThreadId);
base.Post(d, state);
}
}
Installed like this at the very start of Main()
SynchronizationContext.SetSynchronizationContext(new MySynchronizationContext());
It only prints the message once, after the first Run() is completed.
I assumed that's because Task.Run() may detect that it's being called on a threadpool thread and just reuse the current thread but that seems not to be the case because some of my tests resulted in Run 2 and Run 3 running on different threads.
Why does the completion of an awaited Task only runs after the first await?