在ASP.NET Core中,我使用IHttpContextAccessor
来访问当前的HttpContext
。 HttpContextAccessor
uses AsyncLocal<T>
在某种情况下,我试图从请求中启动Task
,在请求结束后(长时间运行,后台任务)应继续运行,并且我试图将其从当前分离执行上下文,以便IHttpContextAccessor
返回null
(否则我将访问无效的HttpContext
)。
我尝试Task.Run
,Thread.Start
,但每次,上下文似乎都会延续,IHttpContextAccessor
会返回旧的上下文,无论我尝试什么(有时甚至是来自其他请求的上下文)。< / p>
如何启动具有干净AsyncLocal
状态的任务,以便IHttpContextAccessor
返回null
?
答案 0 :(得分:2)
最新答案,但可能对其他人有用。您可以通过在提交任务时取消ExecutionContext流来实现此目的:
ExecutionContext.SuppressFlow();
var t = Task.Run(() =>
{
await LongRunningMethodAsync();
});
ExecutionContext.RestoreFlow();
这将防止在提交的任务中捕获ExecutionContext。因此它将具有“干净”的AsyncLocal状态。
如上所述,如果它是占用大量CPU的后台工作,则在ASP.net中不会这样做。
答案 1 :(得分:1)
您可以等待长时间运行的任务,并将HttpContext
设置为在等待内的。对于任务之外的所有代码都是安全的。
[Fact]
public async Task AsyncLocalTest()
{
_accessor = new HttpContextAccessor();
_accessor.HttpContext = new DefaultHttpContext();
await LongRunningTaskAsync();
Assert.True(_accessor.HttpContext != null);
}
private async Task LongRunningTaskAsync()
{
_accessor.HttpContext = null;
}
你可以运行一个单独的线程,这没关系。
Task.Run(async () => await LongRunningTaskAsync());
只需让任务等待清除HttpContext
任务的异步上下文。