Alex Krupka
Alex Krupka

Reputation: 730

Deadlock for GUI task.wait vs Console or ThreadPool

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

Answers (1)

Stephen Cleary
Stephen Cleary

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

Related Questions