C# 埃里克·利珀特';s异步编程示例

C# 埃里克·利珀特';s异步编程示例,c#,asynchronous,C#,Asynchronous,我试图通过Eric Lippert 2011年的例子来理解C#中异步编程的基础知识 我已经为上一个代码示例中引用的方法填写了存根,我希望在命令行上看到的是: Start obtain order Finish obtain order Start obtain ingredients Start obtain recipe Finish obtain ingredients Finish obtain recipe Start recipe prepare meal Finish recipe

我试图通过Eric Lippert 2011年的例子来理解C#中异步编程的基础知识

我已经为上一个代码示例中引用的方法填写了存根,我希望在命令行上看到的是:

Start obtain order
Finish obtain order
Start obtain ingredients
Start obtain recipe
Finish obtain ingredients
Finish obtain recipe
Start recipe prepare meal
Finish recipe prepare meal
Diner receives meal
但是相反,我看到每个方法都被依次调用——似乎没有什么是异步的

我的代码中是否有错误,或者我是否误解了它应该如何工作

非常感谢您的指导

namespace AsyncAwait
    {
    using System;
    using System.Threading.Tasks;

    internal class Program
    {
        internal class Order
        {
        }

        internal class Ingredients
        {
        }

        internal class Recipe
        {
            internal async Task<Meal> PrepareAsync(Ingredients ingredients)
            {
                Console.WriteLine("Start recipe prepare meal");
                await Task.Delay(4 * 1000);
                Console.WriteLine("Finish recipe prepare meal");
                return new Meal();
            }
        }

        internal class Meal
        {
        }

        private class Diner
        {
            internal void Give(Meal meal)
            {
                Console.WriteLine("Diner receives meal");
            }
        }

        async private static Task<Order>ObtainOrderAsync(Diner diner)
        {
            Console.WriteLine("Start obtain order");
            await Task.Delay(3 * 1000);
            Console.WriteLine("Finish obtain order");
            return new Order();
        }

        async private static Task<Ingredients>ObtainIngredientsAsync(Order order)
        {
            Console.WriteLine("Start obtain ingredients");
            await Task.Delay(2 * 1000);
            Console.WriteLine("Finish obtain ingredients");
            return new Ingredients();
        }

        async private static Task<Recipe>ObtainRecipeAsync(Order order)
        {
            Console.WriteLine("Start obtain recipe");
            await Task.Delay(5 * 1000);
            Console.WriteLine("Finish obtain recipe");
            return new Recipe();
        }

        async private static void ServeBreakfast(Diner diner)
        {
            Order order = await ObtainOrderAsync(diner);
            Ingredients ingredients = await ObtainIngredientsAsync(order);
            Recipe recipe = await ObtainRecipeAsync(order);
            Meal meal = await recipe.PrepareAsync(ingredients);
            diner.Give(meal);
        }

        static void Main(string[] args)
        {
            Diner diner = new Diner();
            ServeBreakfast(diner);
            Console.ReadLine();
        }
    }
}
命名空间异步等待
{
使用制度;
使用System.Threading.Tasks;
内部课程计划
{
内部类顺序
{
}
内部类成分
{
}
内部类配方
{
内部异步任务PrepareAsync(配料)
{
Console.WriteLine(“开始配方准备餐”);
等待任务。延迟(4*1000);
控制台。WriteLine(“完成配方准备餐”);
返回新餐();
}
}
内部班级餐
{
}
私家餐馆
{
内部空给(餐)
{
Console.WriteLine(“用餐者收到食物”);
}
}
异步私有静态任务ActainOrderAsync(就餐者)
{
Console.WriteLine(“开始获取订单”);
等待任务。延迟(3*1000);
Console.WriteLine(“完成获取订单”);
返回新订单();
}
异步专用静态任务ActainingRedientsAsync(订单)
{
Console.WriteLine(“开始获取配料”);
等待任务。延迟(2*1000);
控制台。WriteLine(“完成获取配料”);
退回新配料();
}
异步专用静态任务获取RecipeAsync(订单)
{
Console.WriteLine(“开始获取配方”);
等待任务。延迟(5*1000);
控制台。WriteLine(“完成获取配方”);
返回新配方();
}
异步私有静态void ServeBreakfast(Diner-Diner)
{
订单=等待获取订单异步(就餐者);
配料=等待获得配料同步(订单);
配方=等待获得RecipeAsync(订单);
膳食=等待配方。准备同步(配料);
用餐者:给(饭);
}
静态void Main(字符串[]参数)
{
食客食客=新食客();
ServeBreakfast(用餐者);
Console.ReadLine();
}
}
}

这些
Async
方法中的每一个都返回一个可以等待的任务。 当调用
xxxAsync
方法时,启动异步操作,但当
在同一行等待结果(即任务)时,您告诉程序“我需要此方法的结果才能继续”

在您的示例中,我看到的唯一可以并行运行的方法是
actainingredientsasync
actainingrecipeasync
。所有其他方法都需要以前方法的结果

如果希望上述方法并行运行,请首先调用这两个方法,而不必等待它们,然后在继续之前调用它们

async private static void ServeBreakfast(Diner diner)
        {
            Order order = await ObtainOrderAsync(diner);
            Task<Ingredients> ingredientsTask = ObtainIngredientsAsync(order);
            Task<Recipe> recipeTask = ObtainRecipeAsync(order);
            Ingredients ingredients = await ingredientsTask;
            Recipe recipe = await recipeTask
            Meal meal = await recipe.PrepareAsync(ingredients);
            diner.Give(meal);
        }
异步私有静态void ServeBreakfast(Diner-Diner)
{
订单=等待获取订单异步(就餐者);
Task ingredientsTask=获取redientsasync(订单);
任务recipeTask=获取RecipeAsync(订单);
配料=等待配料;
配方=等待接收任务
膳食=等待配方。准备同步(配料);
用餐者:给(饭);
}

这些
Async
方法中的每一个都返回一个可以等待的任务。 当调用
xxxAsync
方法时,启动异步操作,但当
在同一行等待结果(即任务)时,您告诉程序“我需要此方法的结果才能继续”

在您的示例中,我看到的唯一可以并行运行的方法是
actainingredientsasync
actainingrecipeasync
。所有其他方法都需要以前方法的结果

如果希望上述方法并行运行,请首先调用这两个方法,而不必等待它们,然后在继续之前调用它们

async private static void ServeBreakfast(Diner diner)
        {
            Order order = await ObtainOrderAsync(diner);
            Task<Ingredients> ingredientsTask = ObtainIngredientsAsync(order);
            Task<Recipe> recipeTask = ObtainRecipeAsync(order);
            Ingredients ingredients = await ingredientsTask;
            Recipe recipe = await recipeTask
            Meal meal = await recipe.PrepareAsync(ingredients);
            diner.Give(meal);
        }
异步私有静态void ServeBreakfast(Diner-Diner)
{
订单=等待获取订单异步(就餐者);
Task ingredientsTask=获取redientsasync(订单);
任务recipeTask=获取RecipeAsync(订单);
配料=等待配料;
配方=等待接收任务
膳食=等待配方。准备同步(配料);
用餐者:给(饭);
}

您正在逐个等待每项任务:

Order order = await ObtainOrderAsync(diner);
Ingredients ingredients = await ObtainIngredientsAsync(order);
Recipe recipe = await ObtainRecipeAsync(order);
Meal meal = await recipe.PrepareAsync(ingredients);
diner.Give(meal);
当您等待任务时,您会停止方法的执行,直到任务完成

因此,您为任务定义了严格的逐项顺序:在前一个任务完成之前,您不会启动任务

这里有一个例子,其中两个任务是并行完成的,这将为您提供预期的输出

为了(希望)使代码更加清晰,我将您所有的等待分解为单独的语句,用于创建任务和等待任务

async private static void ServeBreakfast(Diner diner)
{
    // first task is to get the order
    Task<Order> getOrder = ObtainOrderAsync(diner);

    // we need to wait for the order, then we 
    // can get the ingredients and recipe in parallel
    Order order = await getOrder;

    // ### Change from your logic: Here we're starting two tasks in parallel. ###
    Task<Ingredients> getIngredients = ObtainIngredientsAsync(order);
    Task<Recipe> getRecipe = ObtainRecipeAsync(order);

    // once we have both the above we can make the meal
    Ingredients ingredients = await getIngredients;
    Recipe recipe = await getRecipe;
    Task<Meal> getMeal = recipe.PrepareAsync(ingredients);

    // when the meal is ready, give it to the diner
    diner.Give(await getMeal);
}
异步私有静态void ServeBreakfast(Diner-Diner)
{
//第一项任务是获得订单
任务getOrder=GetainOrderAsync(就餐者);
//我们需要等待订单,然后
//可以同时获得配料和食谱
订单=等待获取订单;
//######改变你的逻辑:这里我们同时开始两项任务###
任务GetComponents=Getainin