Asp.net

Task.Run 中的 ASP.NET HttpContext.Current

  • September 26, 2016

我有一個在 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 結束。

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