简体   繁体   中英

Why is non awaited Task blocking

I am launching 2 tasks , without await -ing them , and one of them is depending on the other. I am trying to understand why is the following snipped of code blocking.

public class Tasks {
        EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset);

        public async Task Job1() {
            Console.WriteLine("Finished job1");
            handle.Set();
        }

        public async Task Job2() {
            handle.WaitOne();
            Console.WriteLine("Doing Job2 work");
        }
    }

    class Program {
        static async Task Main(string[] args) {

                Tasks seq = new Tasks();
                var t2 =seq.Job2();
                var t1 =seq.Job1();

                await Task.WhenAll(t1, t2);
                Console.WriteLine("finished both");
        }
    }

If i create CPU-bound tasks for both my tasks it works :

var t2=Task.Run(seq.Job2);
var t1=Task.Run(seq.Job1);

I have also tried to put both tasks in a separate task from the main thread and it still blocks:

var bigtask=Task.Run(async()=>{
                         var t2 =seq.Job2();
                         var t1 =seq.Job1();
                     });

If i launch a task without await-ing it isn't it almost the same as starting a new CPU-bound task ? ( Task.Run )

Look at your compiler warnings; they will tell you exactly what's going wrong. Specifically, you're using async without await , so those methods will run synchronously .

Task.Run executes the method on a thread pool thread, which prevents it from running synchronously.

If i launch a task without await-ing it isn't it almost the same as [using Task.Run]?

Every async method starts executing synchronously ; await is the point at which it can behave asynchronously.

async by itself doesn't use any threads (or the thread pool); it's more like a fancier syntax for callbacks. Task.Run does use the thread pool.


To solve your underlying problem (having one task wait for another), the easiest approach is to pass the Task returned from Job1 to the Job2 method, and have Job2 await that task. If that's not possible, then you need an asynchronous kind of signal (not a blocking one like EventWaitHandle ). A one-time asynchronous signal is TaskCompletionSource<T> ; SemaphoreSlim also supports asynchronous waits; and more complex coordination primitives are part of my AsyncEx library .

Declaring methods "async" doesn't automatically make your code multi-threaded. You can assume that your code will run synchronously until something is "awaited".

The issue here is that Job2 will never return, so your code will get stuck. But, for example (and not an actual solution), if you did something like this:

            public async Task Job2()
            {
                await Task.Delay(1000);
                handle.WaitOne();
                Console.WriteLine("Doing Job2 work");
            }

Your program would actually exit, because the function would become asynchronous and return to the caller once the delay is being awaited.

Using synchronization primitives like "EventWaitHandle/ManualResetEvent" should usually be avoided in the TPL(async/await), because they physically block the thread, instead of releasing it and awaiting a callback.

Here is an actual solution:

    public class Tasks
    {
        SemaphoreSlim semaphore = new SemaphoreSlim(0);

        public async Task Job1()
        {
            Console.WriteLine("Finished job1");
            semaphore.Release();
        }

        public async Task Job2()
        {
            await semaphore.WaitAsync();
            Console.WriteLine("Doing Job2 work");
        }
    }

    class Program
    {
        static async Task Main(string[] args)
        {

            Tasks seq = new Tasks();
            var t2 = seq.Job2();
            var t1 = seq.Job1();

            await Task.WhenAll(t1, t2);
            Console.WriteLine("finished both");
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM