Reputation: 708
Maybe I misunderstood something, but I always think that by default, when an incomplete Task is awaited, the current “context” is captured and used to resume the method when the Task completes. But I found quite strange behavior (at least for me) where this is wrong:
private static Task StartTask()
{
return Task.Run(() =>
{
Debug.WriteLine("StartTask thread id = " + Thread.CurrentThread.ManagedThreadId);
});
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
await Task.Run(async () =>
{
Debug.WriteLine("Thread id before await task = " + Thread.CurrentThread.ManagedThreadId);
await StartTask().ConfigureAwait(true);
Debug.WriteLine("Thread id after await task = " + Thread.CurrentThread.ManagedThreadId);
});
}
and I receive such result in debug output
Thread id before await task = 12
StartTask thread id = 13
Thread id after await task = 13
Why did code execution context change after await?
Upvotes: 3
Views: 2143
Reputation: 457207
by default, when an incomplete Task is awaited, the current “context” is captured and used to resume the method when the Task completes
That's correct. The behavior you observed is correct.
The question is: what is the "context" that is captured? It is the current SynchronizationContext
, unless it is null
, in which case it is the current TaskScheduler
.
When Task.Run
executes your delegate, it is executing it on the thread pool. Thus, there is no current SynchronizationContext
. So the current TaskScheduler
is used; note that since there is not actually a task executing (the delegate is executed directly on the thread pool), the current TaskScheduler
is the default TaskScheduler
, which represents the thread pool.
Upvotes: 4