C#异步和等待流程

4
我正在尝试理解异步和等待流程。开始查看John Atten的博客中关于Owin和Katana的代码。在尝试查看执行步骤时,我发现了一些流程中的步骤(步骤9和16),我无法理解为什么执行会遍历这些步骤。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using Owin;
namespace KatanaConsole
{
    //use an alias for OWIN APPFunc
    using AppFunc= Func<IDictionary<string,object>,Task>;
    class Program
    {
        static void Main(string[] args)
        {

            var uri = "http://localhost:8080";

            using ( WebApp.Start<StartUp>(uri))
            {
                Console.WriteLine("Web Server started on port 2323");
                 Console.WriteLine("Server Started; Press enter to Quit");
                Console.ReadLine();
            }
        }
    }

    public class StartUp
    {
        public void Configuration(IAppBuilder appBuilder)
        {
        var firstMiddleware= new Func<AppFunc,AppFunc>(FirstMiddleware);
        var secondMiddleware = new Func<AppFunc, AppFunc>(SecondMiddleware);

        appBuilder.Use(firstMiddleware);
        appBuilder.Use(secondMiddleware);

        }


        public AppFunc FirstMiddleware(AppFunc next)
        {

            AppFunc appFunc = async environment =>
            {
                IOwinContext context = new OwinContext(environment);
                await context.Response.WriteAsync("<h1> Middleware:1 ->  Hello from X1</h1>");
                await next.Invoke(environment);
            };
            return appFunc;
        }

        public AppFunc SecondMiddleware(AppFunc next)
        {

            AppFunc appFunc = async (IDictionary<string, object> environment) =>
            {
                IOwinContext context = new OwinContext(environment);
                await context.Response.WriteAsync("<h1> Middleware:2 ->  Hello from X2</h1>");
                await next.Invoke(environment);
            };
            return appFunc;
        }
    }


}

当我尝试访问localhost:8080时的代码流程:
流程:
进入->第一个中间件
1. IOwinContext context = new OwinContext(environment); 2. await context.Response.WriteAsync("

Middleware:1 -> Hello from X1

"); //响应发送到浏览器 3. await next.Invoke(environment);
进入->第二个中间件
4. IOwinContext context = new OwinContext(environment); 5. await context.Response.WriteAsync("

Middleware:2 -> Hello from X2

");//响应发送到浏览器 6. await next.Invoke(environment);
进入(回到调用方法)->第一个中间件
  1. await next.Invoke(environment);

  2. 退出 -> 第一个中间件

重新进入 -> 第一个中间件

  1. IOwinContext context = new OwinContext(environment);

  2. await context.Response.WriteAsync("<h1> 中间件:1 -> 来自 X1 的问候</h1>"); // 没有向浏览器发送响应

  3. await next.Invoke(environment);

重新进入 -> 第二个中间件

  1. IOwinContext context = new OwinContext(environment);

  2. await context.Response.WriteAsync("<h1> 中间件:2 -> 来自 X2 的问候</h1>");// 没有向浏览器发送响应

  3. await next.Invoke(environment);

重新进入(返回调用方法)->第一个中间件
15. await next.Invoke(environment); 16. 退出 -> 第一个中间件
执行停止 我的问题是为什么它会再次遍历步骤9和16?
另外,即使遍历步骤9和16,响应也不会改变。所以我猜它在那里进行了一些后置条件检查。

2
这个问题对我来说看起来没问题,但确实很奇怪! - tofutim
似乎第二个中间件的“next”应该为null或等效于null。 - tofutim
你在页面上实际看到了两次中间件:1 Hello吗? - tofutim
@TheMar 我只在输出中看到 Middleware:1 一次。 - tofutim
@CollinDauphinee 我在我的端上看到了,他不是在谈论HTML输出,而是你在通过VS调试器逐步执行时所看到的内容。 - tofutim
显示剩余11条评论
1个回答

1

由于浏览器自动发送favicon的第二个请求,步骤9到16被遍历。如果你注意context.Request.Path的上下文,你会发现中间件的第一轮是“/”,第二轮是“/favicon.ico”。实际上,行为取决于你用来发出请求的浏览器。我已经测试了几个浏览器的最新版本和Webkit浏览器(Chrome和Opera)加上IE,我总是会收到关于favicon的请求。在FF中,我只会在第一次得到它并且被缓存。而在Edge中-根本没有被请求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接