Reputation: 730
I'm currently reading through C# in depth(3rd ed) and one of the warnings given is that using a GUI thread with a task.wait is dangerous as it may lead to deadlock. But its not a problem with ThreadPool or Console. My question is why does the thread that is running the task.wait not deadlock so for the following code (taken from book) even a console app (backround) thread would not make it to the catch as it would deadlock.
public static void Main(string[] args = null)
{
var source = new CancellationTokenSource();
var task = TestInt(source.Token);
source.CancelAfter(4000);
Console.WriteLine("Status {0}",task.Status);
try
{
task.Wait();
}
catch (AggregateException e)
{
Console.WriteLine("Caught {0}",e.InnerExceptions[0]);
}
Console.WriteLine("Final Status: {0}",task.Status);
Console.ReadKey();
}
public static async Task TestInt(CancellationToken token, double start = 1)
{
await Task.Delay(TimeSpan.FromSeconds(30), token);
}
Thanks You
Upvotes: 2
Views: 336
Reputation: 456707
I explain this in detail in a blog post.
What happens is that (by default) await
will capture a current "context" and use that context to resume execution of the async
method. This "context" is SynchronizationContext.Current
unless it is null
, in which case it is TaskScheduler.Current
.
In your example, SynchronizationContext.Current
is null
and TaskScheduler.Current
is TaskScheduler.Default
, that is, the thread pool task scheduler. Thus, the async
method is resumed on a thread pool thread and there is no deadlock. The thread pool thread finishes the async
method, completing the Task
, allowing the main thread to finish its wait.
(In the deadlock case, there's a SynchronizationContext
representing the UI thread, so the async
method tries to resume on the UI thread but the UI thread is blocked by calling Wait
).
Upvotes: 6