Is asynchronous method in C # not asynchronous?

Having created the following console application, I am a little puzzled why it works synchronously instead of asynchronously:

class Program { static void Main(string[] args) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var total = CreateMultipleTasks(); stopwatch.Stop(); Console.WriteLine("Total jobs done: {0} ms", total.Result); Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds); } static async Task<int> CreateMultipleTasks() { var task1 = WaitForMeAsync(5000); var task2 = WaitForMeAsync(3000); var task3 = WaitForMeAsync(4000); var val1 = await task1; var val2 = await task2; var val3 = await task3; return val1 + val2 + val3; } static Task<int> WaitForMeAsync(int ms) { Thread.Sleep(ms); return Task.FromResult(ms); } } 

When the application starts, the output is:

Total Jobs Completed: 12,000 ms
Jobs done in: 12003 ms

I would expect something like:

Total Jobs Completed: 12,000 ms
Work done in: 5003 ms

Is this because when I use the Thread.Sleep method, does it stop further execution of the entire application? Or did I miss something important here?

+6
source share
3 answers

You run the task synchronously. You can do something like this:

 static async Task<int> CreateMultipleTasks() { var task1 = Task.Run<int>(() => WaitForMeAsync(5000)); var task2 = Task.Run<int>(() => WaitForMeAsync(3000)); var task3 = Task.Run<int>(() => WaitForMeAsync(4000)); Task.WaitAll(new Task[] { task1, task2, task3 }); return task1.Result + task2.Result + taks3.Result; } 

Using three await in a line will NOT run tasks in parallel. It will simply free the thread while it waits (if you use await Task.Delay(ms) , since Thread.Sleep(ms) is a blocking operation), but the current execution will NOT continue with task2 , and task1 "sleeping".

+1
source

Even when you convert to using Task.Run or Task.Delay , as the other answers suggest , you should avoid using Task.WaitAll locks Task.WaitAll in async methods as much as possible. Mixing asynchronous and synchronous code is usually bad, it increases the number of excessively blocked threads and contributes to deadlocks.

Instead, use await Task.WhenAll and move the pending lock to the top level (i.e. the Main method in this case):

 class Program { static void Main(string[] args) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var total = CreateMultipleTasks(); total.Wait(); stopwatch.Stop(); Console.WriteLine("Total jobs done: {0} ms", total.Result); Console.WriteLine("Jobs done in: {0} ms", stopwatch.ElapsedMilliseconds); } static async Task<int> CreateMultipleTasks() { var task1 = Task.Run(() => WaitForMeAsync(5000)); var task2 = Task.Run(() => WaitForMeAsync(3000)); var task3 = Task.Run(() => WaitForMeAsync(4000)); await Task.WhenAll(new Task[] { task1, task2, task3 }); return task1.Result + task2.Result + task3.Result; } static int WaitForMeAsync(int ms) { // assume Thread.Sleep is a placeholder for a CPU-bound work item Thread.Sleep(ms); return ms; } } 

On the side of the note, check out Stephen Toub "Should I open asynchronous wrappers for synchronous methods?" and Should I expose asynchronous wrappers for synchronous methods?

+4
source

Your WaitForMeAsync method is a simple synchronization method that pretends to be asynchronous.

You do nothing async, and Sleep () just blocks the thread.

Why do you need to delay an asynchronous call? (yes, you can use await Task.Delay(ms) ), more input is needed to help there.

+1
source

All Articles