2014-03-01 110 views
1

這使我困惑。我有這個OWIN /卡塔納中間件:對象被放置得太早?

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)); 

     } 
    } 

,然後啓動類:

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

      app.Use<M1>(); 
     } 
    } 

運行,這將引發一個的ObjectDisposedException在M1:

無法訪問已釋放的對象。對象名稱: 'System.Net.HttpListenerRequest'。

堆棧跟蹤:

在System.Net.HttpListenerRequest.CheckDisposed()在 System.Net.HttpListenerRequest.GetKnownHeader(HttpRequestHeader 報頭)在System.Net.HttpListenerRequest.get_UserHostName()在 Microsoft.Owin.Host.HttpListener.RequestProcessing.RequestHeadersDictionary.TryGetValue在 Microsoft.Owin.HeaderDictionary.TryGetValue(String鍵(字符串 鍵,字符串[] &值),字符串[] & VAL UE)處 Microsoft.Owin.Infrastructure.OwinHelpers.GetHost(在Microsoft.Owin.OwinRequest.get_Host IOwinRequest 請求) Microsoft.Owin.Infrastructure.OwinHelpers.GetHeaderUnmodified(IDictionary的2 headers, String key) at Microsoft.Owin.Infrastructure.OwinHelpers.GetHeader(IDictionary 2個 標頭,String鍵)()

如果我在app.Use()之前刪除了匿名中間件,則不會引發異常。

我做錯了嗎?

+1

你想要做什麼? – theMayer

+0

看起來你正在異步訪問'context',在Owin的一些邏輯處理掉之後。我對歐文一無所知,但這對我來說看起來非常複雜。 – theMayer

+0

我剛開始學習它,但它看起來非常像Node/ExpressJS。 – Evgeni

回答

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>(); 
     } 
    } 
}