Set HttpContext.Current 在 await 的延续中不一样
Set HttpContext.Current is not the same in continuation of await
根据 Stephen Cleary 的 this 回答,我了解到 HttpContext
随 SynchronizationContext
流动。因此,给定以下代码:
public async Task<ActionResult> Index()
{
var outerContext = System.Web.HttpContext.Current = new HttpContext(
new HttpRequest(null, "http://test.com", null),
new HttpResponse(new StreamWriter("C:/Path")));
Console.WriteLine(outerContext.Equals(System.Web.HttpContext.Current));
await Task.Run(
delegate
{
Console.WriteLine(outerContext.Equals(System.Web.HttpContext.Current));
});
Console.WriteLine(outerContext.Equals(System.Web.HttpContext.Current));
return View();
}
我希望控制台输出为:
True
False
True
然而,实际输出是:
True
False
False
调试后,continuation 中的上下文似乎设置为请求的原始上下文,即之前我通过调用 HttpContext.Current = ...
手动设置的上下文。这是什么原因?它是否在执行 await
之后的代码之前的某处设置为请求上下文?
HttpContext.Current
值 未被 保存并由 await
恢复。 await
将捕获 SynchronizationContext.Current
并使用它来恢复执行。
请求开始时,会创建一个新的请求上下文(其中包括一个特定的 HttpContext.Current
实例)。每当 AspNetSynchronizationContext
恢复对该请求上下文的执行时,它将 HttpContext.Current
设置为该请求上下文的实例。
因此,在 await
之后,HttpContext.Current
将与 Index
开头的实例相同,而不是您的代码分配给它的任何实例。
根据 Stephen Cleary 的 this 回答,我了解到 HttpContext
随 SynchronizationContext
流动。因此,给定以下代码:
public async Task<ActionResult> Index()
{
var outerContext = System.Web.HttpContext.Current = new HttpContext(
new HttpRequest(null, "http://test.com", null),
new HttpResponse(new StreamWriter("C:/Path")));
Console.WriteLine(outerContext.Equals(System.Web.HttpContext.Current));
await Task.Run(
delegate
{
Console.WriteLine(outerContext.Equals(System.Web.HttpContext.Current));
});
Console.WriteLine(outerContext.Equals(System.Web.HttpContext.Current));
return View();
}
我希望控制台输出为:
True
False
True
然而,实际输出是:
True
False
False
调试后,continuation 中的上下文似乎设置为请求的原始上下文,即之前我通过调用 HttpContext.Current = ...
手动设置的上下文。这是什么原因?它是否在执行 await
之后的代码之前的某处设置为请求上下文?
HttpContext.Current
值 未被 保存并由 await
恢复。 await
将捕获 SynchronizationContext.Current
并使用它来恢复执行。
请求开始时,会创建一个新的请求上下文(其中包括一个特定的 HttpContext.Current
实例)。每当 AspNetSynchronizationContext
恢复对该请求上下文的执行时,它将 HttpContext.Current
设置为该请求上下文的实例。
因此,在 await
之后,HttpContext.Current
将与 Index
开头的实例相同,而不是您的代码分配给它的任何实例。