首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Eric Lippert的异步编程示例

Eric Lippert的异步编程示例
EN

Stack Overflow用户
提问于 2017-08-25 04:55:00
回答 2查看 629关注 0票数 0

我正在尝试使用Eric Lippert在2011年的C#中的例子来理解Asynchronous Programming - Easier Asynchronous Programming with the New Visual Studio Async CTP中异步编程的基础。

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

代码语言:javascript
复制
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

但是相反,我看到每个方法都是依次调用的--没有任何东西是异步的。

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

非常感谢您的指导。

代码语言:javascript
复制
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();
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-08-25 05:08:38

这些任务方法中的每一个都会返回一个可以进行await编辑的任务。当您调用xxxAsync方法时,您启动了异步操作,但当您在同一行上执行结果(即await )时,您是在告诉程序“在继续之前,我需要此方法的结果”。

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

如果您希望这些提到的方法并行运行,请先调用这两个方法而不使用await,然后在继续操作之前对它们执行await

代码语言:javascript
复制
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);
        }
票数 4
EN

Stack Overflow用户

发布于 2017-08-25 05:10:41

您正在等待每项任务,一个接一个:

代码语言:javascript
复制
Order order = await ObtainOrderAsync(diner);
Ingredients ingredients = await ObtainIngredientsAsync(order);
Recipe recipe = await ObtainRecipeAsync(order);
Meal meal = await recipe.PrepareAsync(ingredients);
diner.Give(meal);

当您await一个任务时,您将停止该方法的执行,直到该任务完成。

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

这里有一个例子,其中两个任务是并行完成的,这应该会给出您期望的输出。

为了(希望)让代码更清晰,我已经将所有的等待分解为创建任务和等待它们的单独语句。

代码语言:javascript
复制
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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45870729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档