Asp.net

從 Application_BeginRequest() 中設置後,AsyncLocal 值為 Null

  • June 26, 2018

在以下範例中,我從內部為我的子類(即 Global.asax)AsyncLocal<string>上的變數設置一個值:HttpApplication``Application_BeginRequest()

public class Global : System.Web.HttpApplication
{
   public static AsyncLocal<string> AsyncLocalState = new AsyncLocal<string>();

   protected void Application_BeginRequest(object sender, EventArgs e)
   {
       AsyncLocalState.Value = HttpContext.Current.Request.Path;
   }

   protected void Application_AuthenticateRequest(object sender, EventArgs e)
   {
       var path = AsyncLocalState.Value;
   }

   protected void Application_EndRequest(object sender, EventArgs e)
   {
       var path = AsyncLocalState.Value;
   }
}

稍後,我將嘗試從處理程序中訪問此AsyncLocal變數的值,例如 MVC 操作方法,甚至只是一個普通的IHttpHandler.

如果我發送了一個足夠大的請求(例如,一個包含超過 15KB 數據的 POST——請求越大,越容易觀察),即使AsyncLocalState從處理程序訪問時,它的值也很有可能為 NULL雖然它設置在BeginRequest.

這可以從一個全新的 ASP.NET 項目中重現,而無需載入任何其他庫/模組/處理程序。

這是一個錯誤嗎?或者也許我做錯了什麼?還是 ASP.NET 太不穩定了?

CallContext.LogicalGetData附加說明:如果我改為使用/ ,則會觀察到完全相同的行為CallContext.LogicalSetData

平台:ASP.NET、.NET 4.6.2,在 Windows 7 上

**更新:**在嘗試探勘之後,我發現了很多引用,但沒有權威的說法是ASP.NET 管道事件之間ExecutionContext 沒有流動(除非它這樣做?)。兩者AsyncLocal和邏輯呼叫上下文都基於ExecutionContext.

最接近權威答案的是David Fowl在 GitHub 上的評論。

如果這些事件不同步執行,則這些事件不會在 ASP.NET 管道事件之間ExecutionContext *流動。*因此,不要使用AsyncLocal或邏輯CallContext來持久化狀態;使用HttpContext.Items.

更新:.NET 4.7.1 添加了一個新的回調方法,HttpApplication.OnExecuteRequestStep根據文件,該方法“為 ASP.NET 管道提供了可擴展性,使開發人員可以輕鬆地在環境上下文場景中實現功能並建構關心 ASP.NET 執行流程的庫(例如,跟踪、分析、診斷和事務)。

這正是人們為了恢復ASP.NET 管道事件之間的AsyncLocal狀態或邏輯所需要的。CallContext

引用自:https://stackoverflow.com/questions/43391498