【问题标题】:Async and await - having trouble understanding异步和等待 - 难以理解
【发布时间】:2021-09-16 18:16:26
【问题描述】:

我已尝试通读 Microsoft 的一些支持,但我试图将其简化,因为我发现其中大部分内容令人困惑。我不明白为什么要执行该方法的其余部分?看起来它一碰到await就跳出来然后再也没有回来,为什么它不回来并从它离开的地方开始呢?我试图让程序在咖啡等待时跳出,十个开始在鸡蛋上,所以让它们异步执行。任何帮助表示赞赏 - 谢谢。

 class Program
{
    static async Task Main(string[] args)
    { 
        Stopwatch stopWatch = new Stopwatch();
        Task<Coffee> coffeeTask = MakeCoffeeAsync(stopWatch);           
        Task<Egg> eggTask = FryEggs(2);
        stopWatch.Stop();
        TimeSpan ts = stopWatch.Elapsed;
        string elapsedTime = String.Format("{0:00}", ts.Seconds);
        Console.WriteLine("Time to make breakfast: " + elapsedTime + " seconds");
    }                

    private static async Task<Egg> FryEggs(int howMany)
    {
        Console.WriteLine("Warming the egg pan...");
        await Task.Delay(3000);
        Console.WriteLine($"cracking {howMany} eggs");
        Console.WriteLine("cooking the eggs ...");
     //  await Task.Delay(8000);
        Console.WriteLine("Put eggs on plate");
        Console.WriteLine("eggs are ready");
        return new Egg();
    }

    private static async Task<Coffee> MakeCoffeeAsync(Stopwatch timerstart)
    {
        timerstart.Start();
        Console.WriteLine("Turning on machine");
        Console.WriteLine("Waiting on machine to be ready");
        await Task.Delay(5000);
        Console.WriteLine("Getting cup");
       // await Task.Delay(4000);
        Console.WriteLine("weighing beans");
        Console.WriteLine("tamping coffee");
       // await Task.Delay(8000);
        Console.WriteLine("pouring coffee into cup");
        Console.WriteLine("coffee is ready" + "\n");
        return new Coffee();
    }
}
class Egg { }
class Coffee { }

这是输出:

Waiting on machine to be ready
Warming the egg pan...
Time to make breakfast: 00 seconds

【问题讨论】:

    标签: c# asynchronous async-await


    【解决方案1】:

    您可以等待所有任务执行完毕:

    await Task.WhenAll(eggTask, coffeeTask);

    static async Task Main(string[] args)
    { 
        Stopwatch stopWatch = new Stopwatch();
        Task<Coffee> coffeeTask = MakeCoffeeAsync(stopWatch);           
        Task<Egg> eggTask = FryEggs(2);
        await Task.WhenAll(eggTask, coffeeTask);// NOTE THIS
        stopWatch.Stop();
        TimeSpan ts = stopWatch.Elapsed;
        string elapsedTime = String.Format("{0:00}", ts.Seconds);
        Console.WriteLine("Time to make breakfast: " + elapsedTime + " seconds");
    } 
    

    另一种选择是添加await关键字:

    static async Task Main(string[] args)
    { 
        Stopwatch stopWatch = new Stopwatch();
        Coffee coffeeTask = await MakeCoffeeAsync(stopWatch);           
        Egg eggTask = await FryEggs(2);
        stopWatch.Stop();
        TimeSpan ts = stopWatch.Elapsed;
        string elapsedTime = String.Format("{0:00}", ts.Seconds);
        Console.WriteLine("Time to make breakfast: " + elapsedTime + " seconds");
    } 
    

    【讨论】:

    • 谢谢你的回复:)
    【解决方案2】:

    异步方法返回一个任务,该任务可以有不同的状态:任务可能仍在运行,也可能已完成。如果添加await,程序将等待任务完成。因为您没有await,所以您的程序不会等到早餐吃完。

    static async Task Main(string[] args)
        { 
            Stopwatch stopWatch = new Stopwatch();
            Task<Coffee> coffeeTask = MakeCoffeeAsync(stopWatch);           
            Task<Egg> eggTask = FryEggs(2);
            Coffee cofee = await cofeeTask;
            Egg egg = await eggTask;
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            string elapsedTime = String.Format("{0:00}", ts.Seconds);
            Console.WriteLine("Time to make breakfast: " + elapsedTime + " seconds");
        } 
    

    【讨论】:

    • 谢谢 - 这似乎是我想要的,但我不认为我理解流程。所以coffeeTask首先被击中,这触发到MakeCoffeeAsync然后在那里遇到一个等待..然后跳回来并启动FryEggs方法.....我不理解任务和变量之间的关系/执行顺序(eggTask/egg & coffeeTask/coffee)
    【解决方案3】:

    你正在解雇/忘记你的任务。您应该等待它们以避免在完成执行之前退出程序:

        static async Task Main(string[] args)
        { 
            Stopwatch stopWatch = new Stopwatch();
            Task<Coffee> coffeeTask = MakeCoffeeAsync(stopWatch);           
            Task<Egg> eggTask = FryEggs(2);
            Coffee coffee = await coffeeTask;
            Egg egg = await eggTask;
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            string elapsedTime = String.Format("{0:00}", ts.Seconds);
            Console.WriteLine("Time to make breakfast: " + elapsedTime + " seconds");
        }
    

    【讨论】:

      【解决方案4】:

      您的流程永远不会返回的原因是因为您没有等待函数 FryEggsMakeCoffeeAsync

      await 是一个关键字,它告诉您的代码在这里停止,直到它有结果。

      如果你想同时煮咖啡和鸡蛋,你想awaitFryEggs

      如果你想煮咖啡,那就煮鸡蛋,你想awaitFryEggsMakeCoffeeAsync 都可以

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      • 谢谢 - 这个答案解释了我可以完成的各种场景以及如何完成一项任务然后启动另一项任务。
      猜你喜欢
      • 2019-09-16
      • 2017-11-04
      • 2018-09-26
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多