在 Task.Run 中等待/异步后将 HttpContext.Current 获取为 null

Getting HttpContext.Current as null after await/async in Task.Run

提问人:user2760913 提问时间:8/11/2023 最后编辑:user2760913 更新时间:8/12/2023 访问量:123

问:

我想在 C# 中使用“即发即弃”方法执行一个方法。每当我用 执行另一个方法时,就会变成 。请让我知道是否有办法在运行方法时保留。Task.RunTask.RunasyncawaitHttpContextnullHttpContextasyncTask.Run

示例代码:

public virtual async Task AddAsync(TModel item)
{
    // Copy HttpContext to use in Task.Run
    var httpRequest = HttpContext.Current?.Request;
    var httpResponse = HttpContext.Current?.Response;
    var contextItems = HttpContext.Current?.Items;

    Task.Run(async () =>
    {
        var taskContext = new HttpContext(httpRequest, httpResponse);

        if (contextItems?.Keys != null)
        {
            foreach (var key in contextItems.Keys)
            {
                taskContext.Items.Add(key, contextItems[key]);
            }
        }

        HttpContext.Current = taskContext; // Context gets copied here correctly.

        try
        {
            await this.InsertAsync(item);
        }
        catch (Exception ex)
        {
            // Log error
        }
    });
}
public virtual async Task InsertAsync(TModel item)
{

    var contextBeforeAwait = HttpContext.Current;  // This is not null
    await this.DoAsyncWork();
    var contextAfterAwait = HttpContext.Current; // Context here becomes null

   // Remaining Insert logic which needs to use HttpContext.Current
}

Web.config 具有:

<httpRuntime targetFramework="4.5" />

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

请让我知道如何避免此问题并在 .HttpContextTask.Run

C# asp.net .NET 异步 async-await

评论

0赞 jdweng 8/11/2023
如果得到 null,则表示连接从未完成,并且出现超时异常。当超时没有响应时,无法保留 HttpContext。

答:

4赞 Stephen Cleary 8/11/2023 #1

我想使用 Task.Run 在 C# 中以“即发即弃”方法执行方法。

你确定这就是你想要的吗?我只是问,因为在 >90% 的人们认为他们想要即发即弃的情况下,这实际上是他们用例的错误解决方案。

具体来说,即发即弃意味着“我不在乎这段代码有时是否没有运行,我也不会收到任何关于它没有运行的日志或通知。对于更新缓存之类的事情来说,这是可以的,但对于更新数据库记录之类的事情来说,这真的很糟糕。

在 Task.Run 中,每当我使用 await 执行另一个异步方法时,HttpContext 就会变为 null。请让我知道是否有办法在 Task.Run 中运行异步方法时保留 HttpContext

不,没有。事实上,你根本不应该从另一个线程访问任何属性或方法。换句话说,a 内部的任何代码不应该访问。它的一部分工作的事实纯粹是偶然的(如果时间不同,它可能会在生产运行时失败)。HttpContextTask.RunHttpContext

更合适的解决方案是先复制您需要的所有内容,然后开始后台工作,传入该数据副本。HttpContext