Question

I have the following code sample:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace asynctest {
    class Program {
        public static void Main (string[] args) {
            var program = new Program ();
            program.run ();
        }

        public Program () {
        }

        public void run () {
            asynctest ();
            Console.WriteLine ("Sync");
            while (true) {
            }
        }

        public async Task asynctest () {
            await Task.Delay (100);
            Console.WriteLine ("Async");
        }
    }
}

When starting this program i would expect the output to be just "Sync", because the asynctest-method is never continued in my code.

Instead it outputs both "Sync" and "Async".

My question is now where exactly the program switches from the run method to the asynctest method to print the "Async" line. From my previous experiences with coroutines this should not happen.

Was it helpful?

Solution

Tasks initiated from Console programs run on the thread pool by default, so your program starts running on thread A. Your asynctest method gets called and as soon as it encounters await Task.Delay (100); it returns and then continues to write out the Sync string. Then thread A blocks on the while loop.

The compiler builds a state machine out of the asynctest method, which upon the finish of Task.Delay(100) resumes execution on thread pool thread B and prints Async. Then thread B terminates. Thread A remains stuck on the while loop.

If you called this from a UI thread you would get a deadlock as await will try to execute the remainder of the asynctest method on the UI thread, which in turn is blocked in the while(true) loop.

Have a look at this article, it explains a bit more about async and await best practices.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top