C# 为什么HttpContext.Current在带有ConfigureAwait的async/await中不为null
我有一个从控制器调用的库异步函数。我期望HttpContext.Current在使用ConfigureAwait(false)进行等待后为null,但在控制器中它不是null。有人能解释一下原因吗C# 为什么HttpContext.Current在带有ConfigureAwait的async/await中不为null,c#,async-await,configureawait,C#,Async Await,Configureawait,我有一个从控制器调用的库异步函数。我期望HttpContext.Current在使用ConfigureAwait(false)进行等待后为null,但在控制器中它不是null。有人能解释一下原因吗 //in libraby public class MyClass { public async Task WaitAsync() { await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
//in libraby
public class MyClass
{
public async Task WaitAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
var httpContext = System.Web.HttpContext.Current; // null, OK
}
}
public class HomeController : Controller
{
public async Task<ActionResult> Index()
{
var class1 = new MyClass();
await class1.WaitAsync();
var httpContext = System.Web.HttpContext.Current; // not null, WHY???
return View("Index");
}
}
//在libraby中
公共类MyClass
{
公共异步任务WaitAsync()
{
等待任务。延迟(TimeSpan.FromSeconds(1))。配置等待(false);
var httpContext=System.Web.httpContext.Current;//null,确定
}
}
公共类HomeController:控制器
{
公共异步任务索引()
{
var class1=新的MyClass();
wait class1.WaitAsync();
var httpContext=System.Web.httpContext.Current;//不为null,为什么???
返回视图(“索引”);
}
}
虽然它比这复杂得多,但你可以把等待
想象成一种与相连的。例如,如果你写:
DoSomeStuff();
await WaitAsync()
DoMoreStuff();
它被改写为:
DoSomeStuff();
WaitAsync().ContinueWith(_ => DoMoreStuff());
.ConfigureAwait
设置继续将在其中执行的上下文。使用ConfigureAwait(true)
(默认值),延续将在与调用方相同的上下文中执行。使用ConfigureAwait(false)
,继续将在线程池上的默认不变上下文中执行。
通过前面的简化,让我们想象一下configurewait(true)
将被重写为ContinueWithSameContext
,而configurewait(false)
将被重写为ContinueWithThreadPool
现在如果我们有嵌套的方法会发生什么?例如,您的代码:
public async Task WaitAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
var httpContext = System.Web.HttpContext.Current; // null, OK
}
public async Task<ActionResult> Index()
{
var class1 = new MyClass();
await class1.WaitAsync();
var httpContext = System.Web.HttpContext.Current; // not null, WHY???
return View("Index");
}
公共异步任务WaitAsync()
{
等待任务。延迟(TimeSpan.FromSeconds(1))。配置等待(false);
var httpContext=System.Web.httpContext.Current;//null,确定
}
公共异步任务索引()
{
var class1=新的MyClass();
wait class1.WaitAsync();
var httpContext=System.Web.httpContext.Current;//不为null,为什么???
返回视图(“索引”);
}
这也被改写了:
public Task WaitAsync()
{
return Task.Delay(TimeSpan.FromSeconds(1))
.ContinueWithThreadPool(_ =>
{
var httpContext = System.Web.HttpContext.Current; // null, OK
});
}
public Task<ActionResult> Index()
{
var class1 = new MyClass();
return class1.WaitAsync().ContinueWithSameContext(_ =>
{
var httpContext = System.Web.HttpContext.Current; // not null, WHY???
return View("Index");
}
}
公共任务WaitAsync()
{
返回任务延迟(时间跨度从秒(1))
.ContinueWithThreadPool(=>
{
var httpContext=System.Web.httpContext.Current;//null,确定
});
}
公共任务索引()
{
var class1=新的MyClass();
返回class1.WaitAsync().ContinueWithSameContext(=>
{
var httpContext=System.Web.httpContext.Current;//不为null,为什么???
返回视图(“索引”);
}
}
通过这种方式重写,您可以看到
WaitAsync
的延续将在与Task Index()
相同的上下文上运行,这解释了为什么HttpContext不为null。wait class1.WaitAsync();
,没有。configurewait(false)
,那么为什么您希望HttpContext为null?@KevinGosse因为等待后的所有代码都在线程池中的线程中执行。我已检查ManagedThreadId是否相同。ConfigureAwait(false)仅在方法调用它之前起作用。