In this article

The Task asynchronous programming model (TAP) provides an abstraction over asynchronous code. You write code as a sequence of statements, just like always. You can read that code as though each statement completes before the next begins. The compiler performs many transformations because some of those statements may start work và return a Task that represents the ongoing work.

Bạn đang xem: Async await c# là gì

Bạn đã xem: Async await c# là gì

That"s the goal of this syntax: enable code that reads like a sequence of statements, but executes in a much more complicated order based on external resource allocation & when tasks complete. It"s analogous khổng lồ how people give instructions for processes that include asynchronous tasks. Throughout this article, you"ll use an example of instructions for making a breakfast to lớn see how the async and await keyword make it easier to lớn reason about code, that includes a series of asynchronous instructions. You"d write the instructions something lượt thích the following list to explain how khổng lồ make a breakfast:

Pour a cup of coffee.Heat up a pan, then fry two eggs.Fry three slices of bacon.Toast two pieces of bread.Add butter & jam to the toast.Pour a glass of orange juice.

If you have experience with cooking, you"d execute those instructions asynchronously. You"d start warming the pan for eggs, then start the bacon. You"d put the bread in the toaster, then start the eggs. At each step of the process, you"d start a task, then turn your attention to lớn tasks that are ready for your attention.

Cooking breakfast is a good example of asynchronous work that isn"t parallel. One person (or thread) can handle all these tasks. Continuing the breakfast analogy, one person can make breakfast asynchronously by starting the next task before the first completes. The cooking progresses whether or not someone is watching it. As soon as you start warming the pan for the eggs, you can begin frying the bacon. Once the bacon starts, you can put the bread into the toaster.

For a parallel algorithm, you"d need multiple cooks (or threads). One would make the eggs, one the bacon, và so on. Each one would be focused on just that one task. Each cook (or thread) would be blocked synchronously waiting for bacon to be ready to lớn flip, or the toast to pop.

Now, consider those same instructions written as C# statements:

using System;using System.Threading.Tasks;namespace AsyncBreakfast{ class Program { static void Main(string args) Coffee cup = PourCoffee(); Console.WriteLine("coffee is ready"); Egg eggs = FryEggs(2); Console.WriteLine("eggs are ready"); Bacon bacon = FryBacon(3); Console.WriteLine("bacon is ready"); Toast toast = ToastBread(2); ApplyButter(toast); ApplyJam(toast); Console.WriteLine("toast is ready"); Juice oj = PourOJ(); Console.WriteLine("oj is ready"); Console.WriteLine("Breakfast is ready!"); private static Juice PourOJ() Console.WriteLine("Pouring orange juice"); return new Juice(); private static void ApplyJam(Toast toast) => Console.WriteLine("Putting jam on the toast"); private static void ApplyButter(Toast toast) => Console.WriteLine("Putting butter on the toast"); private static Toast ToastBread(int slices) { for (int slice = 0; slice

*

The synchronously prepared breakfast, took roughly 30 minutes because the total is the sum of each individual task.

Note

The Coffee, Egg, Bacon, Toast, và Juice classes are empty. They are simply marker classes for the purpose of demonstration, contain no properties, & serve no other purpose.

Computers don"t interpret those instructions the same way people do. The computer will block on each statement until the work is complete before moving on to lớn the next statement. That creates an unsatisfying breakfast. The later tasks wouldn"t be started until the earlier tasks had completed. It would take much longer to create the breakfast, và some items would have gotten cold before being served.

If you want the computer to execute the above instructions asynchronously, you must write asynchronous code.

These concerns are important for the programs you write today. When you write client programs, you want the UI khổng lồ be responsive to user input. Your application shouldn"t make a phone appear frozen while it"s downloading data from the web. When you write hệ thống programs, you don"t want threads blocked. Those threads could be serving other requests. Using synchronous code when asynchronous alternatives exist hurts your ability to lớn scale out less expensively. You pay for those blocked threads.

Successful modern applications require asynchronous code. Without language support, writing asynchronous code required callbacks, completion events, or other means that obscured the original intent of the code. The advantage of the synchronous code is that its step-by-step actions make it easy lớn scan & understand. Traditional asynchronous models forced you to focus on the asynchronous nature of the code, not on the fundamental actions of the code.

Don"t block, await instead

The preceding code demonstrates a bad practice: constructing synchronous code to perform asynchronous operations. As written, this code blocks the thread executing it from doing any other work. It won"t be interrupted while any of the tasks are in progress. It would be as though you stared at the toaster after putting the bread in. You"d ignore anyone talking khổng lồ you until the toast popped.

Let"s start by updating this code so that the thread doesn"t block while tasks are running. The await từ khoá provides a non-blocking way khổng lồ start a task, then continue execution when that task completes. A simple asynchronous version of the make a breakfast code would look like the following snippet:

static async Task Main(string args) Coffee cup = PourCoffee(); Console.WriteLine("coffee is ready"); Egg eggs = await FryEggsAsync(2); Console.WriteLine("eggs are ready"); Bacon bacon = await FryBaconAsync(3); Console.WriteLine("bacon is ready"); Toast toast = await ToastBreadAsync(2); ApplyButter(toast); ApplyJam(toast); Console.WriteLine("toast is ready"); Juice oj = PourOJ(); Console.WriteLine("oj is ready"); Console.WriteLine("Breakfast is ready!");Important

The total elapsed time is roughly the same as the initial synchronous version. The code has yet to lớn take advantage of some of the key features of asynchronous programming.

Tip

The method bodies of the FryEggsAsync, FryBaconAsync, and ToastBreadAsync have all been updated to lớn return Task, Task, and Task respectively. The methods are renamed from their original version khổng lồ include the "Async" suffix. Their implementations are shown as part of the final version later in this article.

This code doesn"t block while the eggs or the bacon are cooking. This code won"t start any other tasks though. You"d still put the toast in the toaster and stare at it until it pops. But at least, you"d respond to lớn anyone that wanted your attention. In a restaurant where multiple orders are placed, the cook could start another breakfast while the first is cooking.

Start tasks concurrently

In many scenarios, you want to lớn start several independent tasks immediately. Then, as each task finishes, you can continue other work that"s ready. In the breakfast analogy, that"s how you get breakfast done more quickly. You also get everything done close khổng lồ the same time. You"ll get a hot breakfast.

The System.Threading.Tasks.Task and related types are classes you can use khổng lồ reason about tasks that are in progress. That enables you khổng lồ write code that more closely resembles the way you"d actually create breakfast. You"d start cooking the eggs, bacon, và toast at the same time. As each requires action, you"d turn your attention to that task, take care of the next action, then await for something else that requires your attention.

Xem thêm: Lý Thuyết, Các Dạng Bài Tập Toán Lớp 6 Cơ Bản, Các Dạng Bài Tập Toán Lớp 6 Thường Gặp

You start a task & hold on lớn the Task object that represents the work. You"ll await each task before working with its result.

Let"s make these changes khổng lồ the breakfast code. The first step is to store the tasks for operations when they start, rather than awaiting them:

Coffee cup = PourCoffee();Console.WriteLine("coffee is ready");Task eggsTask = FryEggsAsync(2);Egg eggs = await eggsTask;Console.WriteLine("eggs are ready");Task baconTask = FryBaconAsync(3);Bacon bacon = await baconTask;Console.WriteLine("bacon is ready");Task toastTask = ToastBreadAsync(2);Toast toast = await toastTask;ApplyButter(toast);ApplyJam(toast);Console.WriteLine("toast is ready");Juice oj = PourOJ();Console.WriteLine("oj is ready");Console.WriteLine("Breakfast is ready!");Next, you can move the await statements for the bacon và eggs to the end of the method, before serving breakfast:

Coffee cup = PourCoffee();Console.WriteLine("coffee is ready");Task eggsTask = FryEggsAsync(2);Task baconTask = FryBaconAsync(3);Task toastTask = ToastBreadAsync(2);Toast toast = await toastTask;ApplyButter(toast);ApplyJam(toast);Console.WriteLine("toast is ready");Juice oj = PourOJ();Console.WriteLine("oj is ready");Egg eggs = await eggsTask;Console.WriteLine("eggs are ready");Bacon bacon = await baconTask;Console.WriteLine("bacon is ready");Console.WriteLine("Breakfast is ready!");