对象过早处置?

时间:2014-03-01 13:02:09

标签: asp.net owin katana

这让我很困惑。我有这个OWIN / Katana中间件:

 class M1 : OwinMiddleware
    {
        public M1(OwinMiddleware next) : base(next) { }
        public override Task Invoke(IOwinContext context)
        {
            return Task.Run(() =>
            {
                Thread.Sleep(200); ; // do something
                string reqUrl = context.Request.Uri.ToString(); //<- throws exception
            })
                .ContinueWith(t => this.Next.Invoke(context));

        }
    }

然后是一个Startup类:

   public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Use((context, next) =>
            {
                return Task.Run(() =>
                {
                }).ContinueWith(t => next());
            });

            app.Use<M1>();
        }
    }

运行它会在M1中抛出ObjectDisposedException:

  

无法访问已处置的对象。对象名称:   'System.Net.HttpListenerRequest'。

堆栈追踪:

  

在System.Net.HttpListenerRequest.CheckDisposed()处   System.Net.HttpListenerRequest.GetKnownHeader(HttpRequestHeader   头部)在System.Net.HttpListenerRequest.get_UserHostName()处   Microsoft.Owin.Host.HttpListener.RequestProcessing.RequestHeadersDictionary.TryGetValue(字符串   key,String []&amp;价值)   Microsoft.Owin.HeaderDictionary.TryGetValue(String key,String []&amp;   价值)   Microsoft.Owin.Infrastructure.OwinHelpers.GetHeaderUnmodified(IDictionary的2 headers, String key) at Microsoft.Owin.Infrastructure.OwinHelpers.GetHeader(IDictionary 2   header,String key)at   Microsoft.Owin.Infrastructure.OwinHelpers.GetHost(IOwinRequest   请求)在Microsoft.Owin.OwinRequest.get_Host()

如果我在 app.Use(); 之前删除该匿名中间件,则不会抛出任何异常。

我做错了吗?

1 个答案:

答案 0 :(得分:1)

您应该使用await而不是ContinueWith来避免在执行中间件之前将控制权返回给owin管道。像这样:

class M1 : OwinMiddleware
{
    public M1(OwinMiddleware next) : base(next) { }
    public override async Task Invoke(IOwinContext context)
    {
        await Task.Run(() =>
        {
            Thread.Sleep(200); ; // do something
            string reqUrl = context.Request.Uri.ToString(); //<- throws exception
        });

        await this.Next.Invoke(context);    
     }
}

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use(async (context, next) =>
        {
            await Task.Run(() => { });
                    await next();
            });

            app.Use<M1>();
        }
    }
}