我正在努力解决这个问题,我想我知道会发生什么,但是却无法解决问题。我将不胜感激。 基本上,我的演示代码是在要煮沸的水壶功能异步运行的情况下煮一杯咖啡,因为这需要很长时间。我一直在等待MakeACupOfCoffee,因为在整个过程完成之前,我不希望秒表计时。这很早就完成了,我知道为什么,但是我不知道如何让代码等待水壶沸腾,同时让其他所有内容继续。
感谢任何指针。
这是我的代码。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace asyncawait
{
class Program
{
static void Main(string[] args)
{
TimeACoffee();
}
private static async Task TimeACoffee()
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
// MakeACupOfCoffee completes before WaitForTheKettleToBoil has finished,
// therefore the await doesn't behave as I want it to
await MakeACupOfCoffee();
stopwatch.Stop();
Console.WriteLine($"\n\nTime taken : {stopwatch.Elapsed}");
Console.ReadLine();
}
private static async Task MakeACupOfCoffee()
{
// This function shouldn't return until everything has completed
// I can't await here otherwise it'd be pointless doing asynchronously
WaitForTheKettleToBoil();
GetCup();
AddCoffee();
AddMilk();
AddSugar();
}
private static Task WaitForTheKettleToBoil()
{
return Task.Run(() =>
{
Console.WriteLine("Waiting for the kettle to boil...");
Thread.Sleep(8000);
});
}
private static void AddMilk()
{
Console.WriteLine("Adding milk");
Thread.Sleep(100);
}
private static void AddSugar()
{
Console.WriteLine("Adding sugar");
Thread.Sleep(100);
}
private static void GetCup()
{
Console.WriteLine("Getting cup");
Thread.Sleep(100);
}
private static void AddCoffee()
{
Console.WriteLine("Adding coffee");
Thread.Sleep(100);
}
}
}
答案 0 :(得分:4)
您的程序(让async
完全传播)
注意 :由于这只是一个测试程序,所以这只是一个出色的解决方案,显然您可能不需要等待任何事情。
但是,由于这是一个async
问题,因此我们可以await
一个Task.Delay
,而且由于C#7.x,我们可以使用async
main
方法
private static async Task TimeACoffee()
{
var stopwatch = new System.Diagnostics.Stopwatch();
stopwatch.Start();
await MakeACupOfCoffee();
stopwatch.Stop();
Console.WriteLine($"\n\nTime taken : {stopwatch.Elapsed}");
Console.ReadLine();
}
private static async Task MakeACupOfCoffee()
{
await WaitForTheKettleToBoil();
await GetCup();
await AddCoffee();
await AddMilk();
await AddSugar();
}
private static async Task WaitForTheKettleToBoil()
{
Console.WriteLine("Waiting for the kettle to boil...");
await Task.Delay(100);
}
private static async Task AddMilk()
{
Console.WriteLine("Adding milk");
await Task.Delay(100);
}
private static async Task AddSugar()
{
Console.WriteLine("Adding sugar");
await Task.Delay(100);
}
private static async Task GetCup()
{
Console.WriteLine("Getting cup");
await Task.Delay(100);
}
private static async Task AddCoffee()
{
Console.WriteLine("Adding coffee");
await Task.Delay(100);
}
或者,您可以这样做
private static async Task MakeACupOfCoffee()
{
// get the cup first, why not?
await GetCup();
// when this is all completed you have a coffee, though coffee drinkers may not like the order.
await Task.WhenAll(WaitForTheKettleToBoil(), AddCoffee(), AddMilk(), AddSugar());
}
或者,您也可以这样做
private static void WaitForTheKettleToBoil()
{
Console.WriteLine("Waiting for the kettle to boil...");
}
private static async Task MakeACupOfCoffee()
{
// start the task (yehaa)
var waitForTheKettleToBoilTask = Task.Run(WaitForTheKettleToBoil);
// need a cup before we can add anything to it
await GetCup();
// when this is all completed you have a coffee
await Task.WhenAll( AddCoffee(), AddMilk(), AddSugar(), waitForTheKettleToBoilTask);
}
注意 :首先喜欢咖啡牛奶和糖的人可能不喜欢你
来自ckuri的评论
哪些差异可能比我更清楚
应注意,您的代码的行为有很大不同。在你的 您煮的第一个代码,等待完成,拿起杯子,等待 完成后,添加咖啡,等待,添加牛奶等待,添加糖并等待。 但是,您可以选择得到杯子,等到得到杯子, 然后开始煮沸,在咖啡机中全部加入咖啡,牛奶和糖 同时等待,直到全部完成
答案 1 :(得分:1)
如果您想保持杯子的拿取和添加非异步的东西(如果这些都是快速操作,那是很好的选择),但是在执行所有这些操作时让水壶保持沸腾状态,则只需保存沸腾任务并返回:
public static Task MakeACupOfCoffee()
{
var boilTask = WaitForKettleToBoil();
GetCup();
AddCoffee();
AddMilk();
AddSugar();
return boilTask;
}
现在,煮沸(任务)开始, 煮沸时,您开始煮杯,添加咖啡,牛奶和糖,最后返回煮沸任务。因此,当您等待MakeACupOfCoffee时,它将等到水壶完成将水煮沸为止。
答案 2 :(得分:0)
如果您不能使用异步,为什么不使用Task.wait?
例如
var t = Task.Run( () => {
// Action on here
} );
t.wait();
动作完成后将停止任务。