I'm starting to learn about async / await in C# 5.0, and I don't understand it at all. I don't understand how it can be used for parallelism. I've tried the following very basic program:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Task task1 = Task1(); Task task2 = Task2(); Task.WaitAll(task1, task2); Debug.WriteLine("Finished main method"); } public static async Task Task1() { await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5))); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10))); Debug.WriteLine("Finished Task2"); } } }
This program just blocks on the call to Task.WaitAll()
and never finishes, but I am not understanding why. I'm sure I'm just missing something simple or just don't have the right mental model of this, and none of the blogs or MSDN articles that are out there are helping.
An async function is a function declared with the async keyword, and the await keyword is permitted within it. The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.
An async function can contain an await expression, that pauses the execution of the function and waits for the passed Promise's resolution, and then resumes the async function's execution and returns the resolved value. You can think of a Promise in JavaScript as the equivalent of Java's Future or C# 's Task.
The await keyword in C# programming language is used to suspend all async methods enclosed until the point where the operations presented by the asynchronous method are completed. In order or a developer to call multiple functions in an asynchronous way, async and await are highly used and recommended.
async/await is single thread event based model. Which allows you to run code out-of-order until the line of code await. In Raku it would actually wait at the await . sub example { my $p = do-something-async; say 'next line'; await $p; say 'done awaiting'}; sub do-something-async { return Promise.in(5).
I recommend you start out with my intro to async
/await
and follow-up with the official MSDN documentation on TAP.
As I mention in my intro blog post, there are several Task
members that are holdovers from the TPL and have no use in pure async
code. new Task
and Task.Start
should be replaced with Task.Run
(or TaskFactory.StartNew
). Similarly, Thread.Sleep
should be replaced with Task.Delay
.
Finally, I recommend that you do not use Task.WaitAll
; your Console app should just Wait
on a single Task
which uses Task.WhenAll
. With all these changes, your code would look like:
class Program { static void Main(string[] args) { MainAsync().Wait(); } public static async Task MainAsync() { Task task1 = Task1(); Task task2 = Task2(); await Task.WhenAll(task1, task2); Debug.WriteLine("Finished main method"); } public static async Task Task1() { await Task.Delay(5000); Debug.WriteLine("Finished Task1"); } public static async Task Task2() { await Task.Delay(10000); Debug.WriteLine("Finished Task2"); } }
Task class is an asynchronous task wrapper. Thread.Sleep(1000) can stop a thread running for 1 second. While Task.Delay(1000) won't stop the current work. See code:
public static void Main(string[] args){ TaskTest(); } private static void TaskTest(){ Task.Delay(5000); System.Console.WriteLine("task done"); }
When running," task done" will show up immediately. So I can assume that every method from Task should be asynchronous. If I replace TaskTest () with Task.Run(() =>TaskTest()) task done won't show up at all until I append a Console.ReadLine(); after the Run method.
Internally, Task class represent a thread state In a State Machine. Every state in state machine have several states such as Start, Delay, Cancel, and Stop.
Now, you may wondering if all Task is asynchronous, what is the purpose of Task.Delay ? next, let's really delay the running thread by using async and await
public static void Main(string[] args){ TaskTest(); System.Console.WriteLine("main thread is not blocked"); Console.ReadLine(); } private static async void TaskTest(){ await Task.Delay(5000); System.Console.WriteLine("task done"); }
async tell caller, I am an asynchronous method, don't wait for me. await inside the TaskTest() ask for waiting for the asynchronous task. Now, after running, program will wait 5 seconds to show the task done text.
Since Task is a state machine, there must be a way to cancel the task while task is in running.
static CancellationTokenSource tokenSource = new CancellationTokenSource(); public static void Main(string[] args){ TaskTest(); System.Console.WriteLine("main thread is not blocked"); var input=Console.ReadLine(); if(input=="stop"){ tokenSource.Cancel(); System.Console.WriteLine("task stopped"); } Console.ReadLine(); } private static async void TaskTest(){ try{ await Task.Delay(5000,tokenSource.Token); }catch(TaskCanceledException e){ //cancel task will throw out a exception, just catch it, do nothing. } System.Console.WriteLine("task done"); }
Now, when the program is in running, you can input "stop" to cancel the Delay task.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With