I am learning async methods in C#, and I am trying to create a small program that calls few methods in sequence with a small delay. at the end of the operation, I am calculating the total time elapsed. Here is my code.
public static async Task<string> MakeCoffeeAsync()
{
Thread.Sleep(3000);
return("Coffee is Ready");
}
public static async Task<string> ToastBreadAsync()
{
Thread.Sleep(2000);
return ("Bread is Toasted");
}
public static async Task<string> ApplyJamToBreadAsync()
{
Thread.Sleep(1000);
return ("Jam added to Bread");
}
public static async void MakeBreakfast()
{
Console.WriteLine("Making Breakfast async way");
Stopwatch sw = new Stopwatch();
sw.Start();
Console.WriteLine(await MakeCoffeeAsync());
Console.WriteLine(await ToastBreadAsync());
Console.WriteLine(await ApplyJamToBreadAsync());
sw.Stop();
Console.WriteLine("Normal Way - Total Time Taken " + sw.ElapsedMilliseconds / 1000 + " Seconds");
}
This is working correctly and I am getting 6 Seconds as output which is correct.
Now I want two tasks to start simultaneously. One Task can start making the coffee (This will take 3 seconds), and second task will Start the Toast (This will take 2 seconds) and Once the toast is ready, the second task will apply Jam to the already toasted bread (This will take 1 second). The sequence is important for Toast. The Jam should only be applied after the Toast is ready.
Expected output : Total elapsed time should be 3 seconds. Because coffee and (Toast + Jam) will run parallelly.
This is what I have tried.
public static async void MakeBreakfastConcurrent()
{
Console.WriteLine("Making Breakfast Concurrent way");
Stopwatch sw = new Stopwatch();
sw.Start();
await Task.Run(() => Console.WriteLine(MakeCoffeeAsync()));
await Task.Run(() => {
Console.WriteLine(ToastBreadAsync());
Console.WriteLine(ApplyJamToBreadAsync());
});
sw.Stop();
Console.WriteLine("Normal Way - Total Time Taken " + sw.ElapsedMilliseconds / 1000 + " Seconds");
}
But this is not working as expected. When I run this, nothing prints after "Making Breakfast Concurrent way"
What am I doing wrong, and how to achieve the correct execution order in concurrent way? (probably something like .then() in JS ?)
>Solution :
Your methods are not asynchronous. You should have gotten a compiler warning. A method is only asynchronous, if at least one of its statements contains the await keyword. The async keyword in your method delcaration alone doesn’t make your method asynchronous! To make your methods asynchronous, replace Thread.Sleep by await Task.Delay:
public static async Task<string> MakeCoffeeAsync()
{
await Task.Delay(3000);
return("Coffee is Ready");
}
public static async Task<string> ToastBreadAsync()
{
await Task.Delay(2000);
return ("Bread is Toasted");
}
public static async Task<string> ApplyJamToBreadAsync()
{
await Task.Delay(1000);
return ("Jam added to Bread");
}
To run your methods concurrently, first call the methods without awaiting them. Then await all tasks and print the results:
Task<string> coffeTask = MakeCoffeeAsync();
Task<string> breadTask = ToastBreadAsync();
Task<string> jamTask = ApplyJamToBreadAsync();
await Task.WhenAll(coffeeTask, breadTask, jamTask);
string coffeeResult = await coffeTask;
string breadResult = await breadTask;
string jamResult = await jamTask;
Console.WriteLine(coffeeResult);
Console.WriteLine(breadResult );
Console.WriteLine(jamResult );
Online-demo: https://dotnetfiddle.net/vhJLtk