Asp.net
Task.Run 中的 ASP.NET HttpContext.Current
我有一個在 ASP.NET MVC 應用程序中使用的以下程式碼範例。這段程式碼的目的是創建“一勞永逸”的請求,以便對一些長時間執行的操作進行排隊。
public JsonResult SomeAction() { HttpContext ctx = HttpContext.Current; Task.Run(() => { HttpContext.Current = ctx; //Other long running code here. }); return Json("{ 'status': 'Work Queued' }"); }我知道這不是在非同步程式碼中處理 HttpContext.Current 的好方法,但目前我們的實現不允許我們做其他事情。我想了解這段程式碼有多危險……
**問題:**理論上是否有可能在 Task.Run 中設置 HttpContext,將上下文設置為完全另一個請求?
我認為是的,但我不確定。我如何理解:Request1 由執行緒池中的 Thread1 處理,然後當 Thread1 完全處理另一個請求(Request2)時,Task.Run 中的程式碼會將上下文從 Request1 設置為 Request2。
也許我錯了,但我對 ASP.NET 內部的了解並不能讓我正確理解它。
謝謝!
讓我來談談你的一些內部情況:
public static HttpContext Current { get { return ContextBase.Current as HttpContext; } set { ContextBase.Current = value; } } internal class ContextBase { internal static object Current { get { return CallContext.HostContext; } set { CallContext.HostContext = value; } } } public static object HostContext { get { var executionContextReader = Thread.CurrentThread.GetExecutionContextReader(); object hostContext = executionContextReader.IllogicalCallContext.HostContext; if (hostContext == null) { hostContext = executionContextReader.LogicalCallContext.HostContext; } return hostContext; } set { var mutableExecutionContext = Thread.CurrentThread.GetMutableExecutionContext(); if (value is ILogicalThreadAffinative) { mutableExecutionContext.IllogicalCallContext.HostContext = null; mutableExecutionContext.LogicalCallContext.HostContext = value; return; } mutableExecutionContext.IllogicalCallContext.HostContext = value; mutableExecutionContext.LogicalCallContext.HostContext = null; } }所以
var context = HttpContext.Current;等於(虛擬碼)
var context = CurrentThread.HttpContext;在你裡面
Task.Run發生這樣的事情CurrentThread.HttpContext= context;
Task.Run將使用執行緒池中的執行緒啟動新任務。所以你說你的新執行緒“HttpContext 屬性”是對啟動執行緒“HttpContext 屬性”的引用——到目前為止一切都很好(以及在啟動執行緒完成後你將面臨的所有 NullReference/Dispose 異常)。問題是如果在你的//Other long running code here.你有這樣的聲明
var foo = await Bar();一旦你點擊等待,你目前的執行緒將返回到執行緒池,並且在 IO 完成後你從執行緒池中獲取新執行緒 - 想知道它的“HttpContext 屬性”是什麼,對吧?我不知道 :) 你很可能會以 NullReferenceException 結束。