C# Async Await, Simply
Tags: csharp, beginners, dotnet
Published: 2019-09-26 06:00:10

# One at a time 

Code is executed to achieve a purpose. Usually it's run as a series of steps, eventually leading to a final result. Each of the steps take some time to execute, and running them synchronously, one after the other, can take a significant amount of time.

![alt text](https://i0.wp.com/www.whatsageek.com/wp-content/uploads/2014/12/Dr-Evil.jpg?resize=746%2C436)

Say you're a Doctor of Evil - a Dr. Evil if you will. And you want to run a successful criminal enterprise to take over the world; maybe you're looking to make _One Million Dollars_... Would it be the most effective way to run all of your plans one after the other?

# Running an _Evil_ Empire

![alt text](https://media.giphy.com/media/jd6TVgsph6w7e/source.gif)

The first thing you'll need, as an _evil mastermind_, is of course an **Evil Lair**.

* `Task.Delay(x)` gives a logical delay of `x` milliseconds without blocking the current thread

```csharp
public static void BuildAnEvilLair()
{
	await Task.Delay(5000);
	Console.WriteLine("Evil Lair Built!");
}
```

After you build your lair, you're going to need to hire some henchman.

```csharp
public static void HireSomeHenchman()
{
	await Task.Delay(2000);
	Console.WriteLine("Henchman Hired!");
}
```

And of course, you'll need to create a mini clone of yourself.

```csharp
public static void MakeMiniClone()
{
	await Task.Delay(3000);
	Console.WriteLine("Mini Clone Created!");
}
```

Once all of this is in place, you can start working on your _Super Evil Plan_!

```csharp
public static void SuperEvilPlan()
{
	await Task.Delay(4000);
	Console.WriteLine("Super Evil Plan Completed!");
}
```

And let's not forget threatening world leaders with your _Super Evil Plan_ and ransoming _One Million Dollars_.

![alt text](https://media.giphy.com/media/BZlNhp9L5WINi/giphy.gif)

```csharp
public static int MakeOneMillionDollars()
{

	await Task.Delay(2000);
	Console.WriteLine("Million Dollars Made!");
	return 1000000;
}
```

Finally, when everything has been completed, we can achieve **World Domination**.

```csharp
public static void WorldDomination()
{
	await Task.Delay(6000);
	Console.WriteLine("World Domination Achieved!");
}
```

Putting our plan together,

```csharp
BuildAnEvilLair();
HireSomeHenchman();
MakeMiniClone();
SuperEvilPlan();
var money = MakeOneMillionDollars();
WorldDomination();
```

which takes 22 000ms (or 22 seconds) _synchronously_.

# All at once

![alt text](https://media.giphy.com/media/l3mZjke44skqBVJBe/source.gif)

Many of the steps in such a synchronous _plan_ can be executed in parallel, _asynchronously_. So how is this done?

First, all the methods will be made asynchronous with the `async` descriptor, and their executing code will be awaited.

Awaiting asynchronous code, the awaiting code is processed asynchronously, and the code following the `await` is added as a _continuation_ to the `await`. The _continuation_ will be run after the code being _awaited_ has run its duration and been successfully executed.

```csharp
public static async Task BuildAnEvilLair()
{
	await Task.Delay(5000);
	Console.WriteLine("Evil Lair Built!");
}

public static async Task HireSomeHenchman()
{
	await Task.Delay(2000);
	Console.WriteLine("Henchman Hired!");
}

public static async Task MakeMiniClone()
{
	await Task.Delay(3000);
	Console.WriteLine("Mini Clone Created!");
}

public static async Task SuperEvilPlan()
{
	await Task.Delay(4000);
	Console.WriteLine("Super Evil Plan Completed!");
}

public static async Task<int> MakeOneMillionDollars()
{
	await Task.Delay(2000);
	Console.WriteLine("Million Dollars Made!");
	return 1000000;
}

public static async Task WorldDomination()
{
	await Task.Delay(6000);
	Console.WriteLine("World Domination Achieved!");
}
```

With output

> Million Dollars Made!
> Super Evil Plan Completed!
> Mini Clone Created!
> Evil Lair Built!
> Henchman Hired!
> World Domination Achieved!

![alt text](https://media.giphy.com/media/SCaWhPSWvBxZK/giphy.gif)

Clearly this is a **mess**. Everything is happening **at once**. It's really fast - only dependent on the slowest method (6000ms). It's obvious that some calls are dependent on others. Now we need to _synchronise_ them with each other.

# Effectively Asynchronous

So, as an _Evil Mastermind_, which tasks would you run and in which order?

First, we need an evil lair. After that we can hire some henchman and create a mini clone of ourselves. Then we can come up with a Super Evil Plan, after which we can make One Million Dollars and achieve World Domination.

Changing the executing code we can achieve this by using the right mix of `await` and `Task.WaitAll`. `Task.WaitAll` fires off all the tasks asynchronously and finishes _awaiting_ those tasks once all the tasks have completed - so the `Task.WaitAll` takes as long as the longest task it's _awaiting_. 

Let's try this again.

```csharp
// First we need an Evil Lair
await BuildAnEvilLair();

// Next, hire Henchman and create a Clone (asynchronously)
Task.WaitAll(HireSomeHenchman(), MakeMiniClone());

// Now, come up with the evil plan
await SuperEvilPlan();

// And finally, make One Million Dollars (and achieve World Domination)
Task.WaitAll(MakeOneMillionDollars(), WorldDomination());
```

With output,

> Evil Lair Built!
> Henchman Hired!
> Mini Clone Created!
> Super Evil Plan Completed!
> Million Dollars Made!
> World Domination Achieved!

Taking a cool 18 000ms (18 seconds). 4 seconds less than the _synchronous_ implementation.

![](https://media.giphy.com/media/brDwVn5kGIz3W/source.gif)

So remember, next time you want to become an _Evil Genius_ consider asynchronous execution and some time. If it's up to those _darn_ super spies, every second counts!