H2ONaCl
H2ONaCl

Reputation: 11279

Why do .NET console programs not deadlock the way UI programs do?

UI programs (WPF or Windows Forms) and ASP.NET programs should use async and await thoroughly to avoid deadlock. Why does a console program not have the same requirement? For example in the following blocking on await in MyGetAsync and also blocking at .Result in MyInvoker does not cause a deadlock.

static void Main(string[] args)
{
    Console.WriteLine("test...");
    MyInvoker();
    Console.WriteLine("END. Press the Enter key to exit the program.");
    Console.ReadLine();
}
internal static void MyInvoker()
{
    Task<string> task = MyGetAsync();
    string s = task.Result;
    if (s.Contains("doctype") || s.Contains("DOCTYPE"))
        Console.WriteLine("received an HTML page");
    else
        throw new Exception(s);
}
internal static async Task<string> MyGetAsync()
{
    using (var httpClient = new HttpClient())
    {
        string response = await httpClient.GetStringAsync("https://google.com");
        return response;
    }
}

Upvotes: 0

Views: 39

Answers (2)

Dan Chase
Dan Chase

Reputation: 1042

You interact differently with a UI such as Windows Forms and WPF, versus a console app. You generally wait until a console app tells you to do something, before you do, then you wait until it's done. As a result, there's no need to worry about thread logic contending with UI resources. With Windows Forms and WPF (any GUI really) you have a lot going on that you may not know about, and people have a hard time remembering to keep business logic out of the UI thread, or it really wouldn't be much of a problem. Now, many times, people do that when they've already written a huge chunk of their program before it finally locks up, and at that point, they have to revisit quite a lot in order to thread it out correctly..

Upvotes: 1

Stephen Cleary
Stephen Cleary

Reputation: 456717

There are two parts to the classic deadlock:

  1. Blocking on asynchronous code (that does not use ConfigureAwait(false) everywhere).
  2. An asynchronous context that only permits one thread in at a time.

Your example code always does (1) in both environments. The difference is in (2). Specifically, UI apps have a SynchronizationContext for their UI thread so that await will naturally return to the UI thread after the await completes. Console apps do not have that context, so the deadlock does not happen.

Upvotes: 1

Related Questions