Trying to simulate making tea by using Tasks in C# (.Net6). My problem is I want BoilWater & (GetCup, InsertTeaBag and GetMilk) to run synchronously, and then after they are finished the rest of the methods are to run. I used the await keyword but it didn't work.
My Code:
await MakeTea();
async Task MakeTea()
{
await Task.Run(() => {
Task.Run(() => BoilWater());
Task.Run(() =>
{
GetCup();
InsertTeabag();
GetMilk();
});
});
PourBoiledWater();
StirTeaBag();
PourMilk();
FinalStir();
}
async Task BoilWater()
{
Console.WriteLine("boiling water...");
Thread.Sleep(20000);
Console.WriteLine("finished boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task InsertTeabag()
{
Console.WriteLine("taking out tea bag box out of cupboard and insert it into cup...");
Thread.Sleep(5000);
Console.WriteLine("finished inserting teabag!!!");
Console.WriteLine("-----------------------");
}
async Task GetCup()
{
Console.WriteLine("taking out tea cup out of cupboard...");
Thread.Sleep(2000);
Console.WriteLine("finished taking out cup!!!");
Console.WriteLine("-----------------------");
}
async Task GetMilk()
{
Console.WriteLine("taking out milk out of the fridge...");
Thread.Sleep(4000);
Console.WriteLine("finished taking getting milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourMilk()
{
Console.WriteLine("pouring milk...");
Thread.Sleep(3000);
Console.WriteLine("finished pouring milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourBoiledWater()
{
Console.WriteLine("pouring boiling water...");
Thread.Sleep(3000);
Console.WriteLine("finished pouring boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task StirTeaBag()
{
Console.WriteLine("stirring teabag with boiled water...");
Thread.Sleep(9000);
Console.WriteLine("finihsed stirring!!!");
Console.WriteLine("-----------------------");
}
async Task FinalStir()
{
Console.WriteLine("stirring milk into tea...");
Thread.Sleep(2000);
Console.WriteLine("finished stirring!!!");
Console.WriteLine("-----------------------");
}
Thank you in advance for your help.
CodePudding user response:
await is always about chaining asynchrony, on each level. Using async and await together. You are chaining it in a wrong way
await Task.Run(() => { // returned task only start other tasks and don't wait for their end.
Task.Run(() => BoilWater());
Task.Run(() =>
{
GetCup();
InsertTeabag();
GetMilk();
});
});
You need kind of:
var boilTask = Task.Run(async () => await BoilWater());
var otherPreparationsTask = Task.Run(async () =>
{
await GetCup();
await InsertTeabag();
await GetMilk();
}); // you will get only one task for all this nethods. After all of them get completed consequently
await Task.WhenAll(new[] {boilTask, otherPreparationsTask});
And you must not use Sleep with async keyword. You must use
await Task.Delay(...)
Here is my output and source code:
boiling water...
taking out tea cup out of cupboard...
finished taking out cup!!!
-----------------------
taking out tea bag box out of cupboard and insert it into cup...
finished inserting teabag!!!
-----------------------
taking out milk out of the fridge...
finished taking getting milk!!!
-----------------------
finished boiling water!!!
-----------------------
pouring boiling water...
finished pouring boiling water!!!
-----------------------
stirring teabag with boiled water...
finihsed stirring!!!
-----------------------
pouring milk...
finished pouring milk!!!
-----------------------
stirring milk into tea...
finished stirring!!!
-----------------------
await MakeTea();
async Task MakeTea()
{
var boilTask = Task.Run(async () => await BoilWater());
var otherTasks = Task.Run(async () =>
{
await GetCup();
await InsertTeabag();
await GetMilk();
});
await Task.WhenAll(new[] {boilTask, otherTasks});
await PourBoiledWater();
await StirTeaBag();
await PourMilk();
await FinalStir();
}
async Task BoilWater()
{
Console.WriteLine("boiling water...");
await Task.Delay(20000);
Console.WriteLine("finished boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task InsertTeabag()
{
Console.WriteLine("taking out tea bag box out of cupboard and insert it into cup...");
await Task.Delay(5000);
Console.WriteLine("finished inserting teabag!!!");
Console.WriteLine("-----------------------");
}
async Task GetCup()
{
Console.WriteLine("taking out tea cup out of cupboard...");
await Task.Delay(2000);
Console.WriteLine("finished taking out cup!!!");
Console.WriteLine("-----------------------");
}
async Task GetMilk()
{
Console.WriteLine("taking out milk out of the fridge...");
await Task.Delay(4000);
Console.WriteLine("finished taking getting milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourMilk()
{
Console.WriteLine("pouring milk...");
await Task.Delay(3000);
Console.WriteLine("finished pouring milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourBoiledWater()
{
Console.WriteLine("pouring boiling water...");
await Task.Delay(3000);
Console.WriteLine("finished pouring boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task StirTeaBag()
{
Console.WriteLine("stirring teabag with boiled water...");
await Task.Delay(9000);
Console.WriteLine("finihsed stirring!!!");
Console.WriteLine("-----------------------");
}
async Task FinalStir()
{
Console.WriteLine("stirring milk into tea...");
await Task.Delay(2000);
Console.WriteLine("finished stirring!!!");
Console.WriteLine("-----------------------");
}
CodePudding user response:
Use await Task.Delay(int)
instead of Thread.Sleep(int)
Also, you don't have performed wait all for t1 and t2.
once t1 and t2 are completed, then you have to perform another task so you need to wait for that using WhenAll() or WaitAll();
await MakeTea();
async Task MakeTea()
{
await Task.Run(async () => {
Task t1= Task.Run(async() => await BoilWater());
Task t2= Task.Run(async() =>
{
await GetCup();
await InsertTeabag();
await GetMilk();
});
await Task.WhenAll(t1,t2);
});
await PourBoiledWater();
await StirTeaBag();
await PourMilk();
await FinalStir();
}
async Task BoilWater()
{
Console.WriteLine("boiling water...");
await Task.Delay(20000);
Console.WriteLine("finished boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task InsertTeabag()
{
Console.WriteLine("taking out tea bag box out of cupboard and insert it into cup...");
await Task.Delay(5000);
Console.WriteLine("finished inserting teabag!!!");
Console.WriteLine("-----------------------");
}
async Task GetCup()
{
Console.WriteLine("taking out tea cup out of cupboard...");
await Task.Delay(2000);
Console.WriteLine("finished taking out cup!!!");
Console.WriteLine("-----------------------");
}
async Task GetMilk()
{
Console.WriteLine("taking out milk out of the fridge...");
await Task.Delay(4000);
Console.WriteLine("finished taking getting milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourMilk()
{
Console.WriteLine("pouring milk...");
await Task.Delay(3000);
Console.WriteLine("finished pouring milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourBoiledWater()
{
Console.WriteLine("pouring boiling water...");
await Task.Delay(3000);
Console.WriteLine("finished pouring boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task StirTeaBag()
{
Console.WriteLine("stirring teabag with boiled water...");
await Task.Delay(9000);
Console.WriteLine("finihsed stirring!!!");
Console.WriteLine("-----------------------");
}
async Task FinalStir()
{
Console.WriteLine("stirring milk into tea...");
await Task.Delay(2000);
Console.WriteLine("finished stirring!!!");
Console.WriteLine("-----------------------");
}
CodePudding user response:
Thread.Sleep(9000)
this is to make a busy waiting (block the thread ) to use asynchronous method, you should callawait Task.Delay(9000)
insted- whenever you use
async
in your method, then the body of method should containawait
keyword
await MakeTea();
async Task MakeTea()
{
var BoilerTask = BoilWater();
await GetCup();
await InsertTeabag();
await GetMilk();
await BoilerTask;
await PourBoiledWater();
await StirTeaBag();
await PourMilk();
await FinalStir();
}
async Task BoilWater()
{
Console.WriteLine("boiling water...");
await Task.Delay(20000);
Console.WriteLine("finished boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task InsertTeabag()
{
Console.WriteLine("taking out tea bag box out of cupboard and insert it into cup...");
await Task.Delay(5000);
Console.WriteLine("finished inserting teabag!!!");
Console.WriteLine("-----------------------");
}
async Task GetCup()
{
Console.WriteLine("taking out tea cup out of cupboard...");
await Task.Delay(2000);
Console.WriteLine("finished taking out cup!!!");
Console.WriteLine("-----------------------");
}
async Task GetMilk()
{
Console.WriteLine("taking out milk out of the fridge...");
await Task.Delay(4000);
Console.WriteLine("finished taking getting milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourMilk()
{
Console.WriteLine("pouring milk...");
await Task.Delay(3000);
Console.WriteLine("finished pouring milk!!!");
Console.WriteLine("-----------------------");
}
async Task PourBoiledWater()
{
Console.WriteLine("pouring boiling water...");
await Task.Delay(3000);
Console.WriteLine("finished pouring boiling water!!!");
Console.WriteLine("-----------------------");
}
async Task StirTeaBag()
{
Console.WriteLine("stirring teabag with boiled water...");
await Task.Delay(9000);
Console.WriteLine("finihsed stirring!!!");
Console.WriteLine("-----------------------");
}
async Task FinalStir()
{
Console.WriteLine("stirring milk into tea...");
await Task.Delay(2000);
Console.WriteLine("finished stirring!!!");
Console.WriteLine("-----------------------");
}
if you like to prepare a complete breakfast, here is a good and Fast recipe by Microsoft