Async and Await and what is it actually doing?
Tags: dotnet, csharp
Published: 2021-03-27 17:15:49

Ever write a function that calls another function that happens to be asynchronous? Intellisense complains that the function being called is not being awaited. What did you do? Add the keyword await and voila! Your issue was resolved. 

But what is your code doing? 

No time to ponder on that, create the pull request and wait for your lead to dig into you and hope that they don't ask you to explain the use of `await` or why you had to mark your function as `async`. You can't give them the inclination that you don't know what you're doing! 

### What it's not
Async programming is not parallel programming. It does not mean "thread A go do X" and "thread B go do Z". It means the "thread" that you are using right now, will do all the tasks but in a order that will best optimize performance. A popular example is someone making breakfast. Say you are making eggs and toast. Your first step is to heat up the pan. *While* the pan is heating up, take the eggs out of the fridge and the bread out of the pantry. Now your pan is hot, break the eggs to start frying. *While* the eggs are frying, place the bread in the toaster. Your eggs are done. Plate them. Your toast is ready. Plate that too. Done. It took one person, one thread but the tasks were done in a manner where both items would be cooked simultaneously. 

### Async
`Async` enables the use of the `await` keyword in the method. A method marked with an async keyword, executes like any other function until it gets to the line with the `await` keyword. 

### Await
`Await` provides a non-blocking way to start a task. How? Through method control flow. When a task to download a file has been called, the thread does not wait until its completion. It yields control to the calling method to continue work until the result of the file download is needed. The `await` keyword indicates the point at which the method is suspended and the control has been passed to the calling function if the task has not been completed. 

If the awaited `async` method has been completed, it returns the result stored into a `Task` object. 

Here is a helpful diagram of the control flow:
![async control flow](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/media/task-asynchronous-programming-model/navigation-trace-async-program.png)

### Task Asynchronous Programming (TAP) model

C# uses the Task Asynchronous Programming (TAP) model to provide an abstraction over asynchronous code. This allows us to read and write code in a synchronous fashion while performing asynchronous tasks. The compiler does all the work figuring out when methods need to be suspended and the order of their execution flows. Doing this work without language support would require a lot of code written by the developer that would convolute the intent of the business logic being executed. 

The TAP model essentially utilizes `Task` objects to hold the async method's results, progress, and other information. You can store the result of an async method to an object of type `Task`. When the result is needed, you can `await` that `Task` object to retrieve the result of the async method.  
```
public async Task cookBreakfast() {
    // Start toasting the bread and let me hold onto an object
    // that I can use to retrieve the result later
    Task toastTask = toastBreadAsync();

    Console.log("Frying eggs");

    // I need the result of ToastBreadAsync() now
    await toastTask;
    Console.WriteLine("toast is ready");
}

public async Task toastBreadAsync(){
    Console.WriteLine("Starting on toast");
    await someToastyThings();
    Console.WriteLine("Done Toasting!");
}
```

The result of the above code execution would look something like this: 
```
"Starting on toast"
"Frying eggs"
"Done Toasting!"
"toast is ready"
```

Lets walk through this.

1. cookBreakfast() is called.
2. toastBreadAsync() is called
3. "Starting on toast" is printed
4. someToastyThings() is called and awaited. Yields control to cookBreakfast()
5. toastBreadAsync() has it's Task stored into toastTask
6. "Frying eggs" is printed
7. toastTask is awaited. Control is back to someToastyThings(); Is it done? Lets say it is. 
8. "Done Toasting" is printed
9. Control comes back to cookBreakfast
10. "toast is ready" is printed


### Sync vs Async
It is important to call out the differences in building asynchronous applications vs synchronous ones specially with the TAP model. 
* You'll note that a synchronous method returns a value when the method is complete. However, an asynchronous method will return a `Task` immediately and when it eventually completes, it will store the result in the `Task`. 
* The next is control flow. When a method is awaited and the results of the method are not yet available, the control is yielded to the calling function. On the flip side, with synchronous programming, control will continue to the next line. 

### Further Reading
I wasn't born with this information. Here are some really good resources to go deeper on the subject.
* [Programming Guide - Async](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/)
* [There Is No Thread](https://blog.stephencleary.com/2013/11/there-is-no-thread.html)


I hope this helped scratch the surface on asynchronous programming in dotnet. There is a lot more fancy things that can be done when it comes to this topic but having the fundamental understanding of what is happening in your application is the first step. 

Go onward with your PRs with confidence!