使用干净的AsyncLocal状态

时间:2017-06-26 10:43:54

标签: asp.net-core .net-core asp.net-core-1.1

在ASP.NET Core中,我使用IHttpContextAccessor来访问当前的HttpContextHttpContextAccessor uses AsyncLocal<T>

在某种情况下,我试图从请求中启动Task,在请求结束后(长时间运行,后台任务)应继续运行,并且我试图将其从当前分离执行上下文,以便IHttpContextAccessor返回null(否则我将访问无效的HttpContext)。

我尝试Task.RunThread.Start,但每次,上下文似乎都会延续,IHttpContextAccessor会返回旧的上下文,无论我尝试什么(有时甚至是来自其他请求的上下文)。< / p>

如何启动具有干净AsyncLocal状态的任务,以便IHttpContextAccessor返回null

2 个答案:

答案 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任务的异步上下文。