c# - ConfigureAwait(false) 没有按预期使 HttpContext NULL

标签 c# .net asp.net-mvc async-await

在使用async/await时,为避免死锁,建议使用ConfigureAwait(false)一直到最后一层。我知道使用 ConfigureAwait(false) 也会使当前的 HttpContext 为空。 Article

下面的示例代码只是为了理解为什么 ConfigureAwait(false) 没有在预期时将 HttpContext 设为 NULL,而在不需要时将其设为 NULL。

Controller

public class MyController : Controller
{
    private readonly MyService _service = new MyService();
    private readonly MyMapper _mapper = new MyMapper();        


    public async Task<ActionResult> DoSomething()
    {
        var data = await _service.GetData().ConfigureAwait(false);

        // EXPECTED: Below, HttpContext should NOT NULL
        // ACTUAL: HttpContext is NOT NULL as expected
        if (HttpContext == null)
        {
            throw new ArgumentNullException("context");
        }

        var model = _mapper.Map(data);

        return View(model);
    }
}

对数据源进行异步调用以获取数据的服务

public class MyService
{
    public async Task<string> GetData()
    {
        // EXPECTED: HttpContext should be NULL here since we are calling 
        //this method from the Controller with ConfigureAwait(false)     

        // ACTUAL: HttpContext is NOT NULL, WHY?
        if(HttpContext.Current == null)
        {
            throw new ArgumentNullException("context");
        }

        using (var client = new HttpClient())
        {
            var response = await client.GetAsync("http://url").ConfigureAwait(false);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        }
    }
}

映射器类将数据映射到模型

public class MyMapper
{
    public MyModel Map(string data)
    {
        // EXPECTED:  HttpContext should NOT NULL here since async call is already done.
        // ACTUAL: HttpContext is NULL here. WHY?
        if (HttpContext.Current == null)
        {
            throw new ArgumentNullException("context");
        };

        return new MyModel()
        {
            Message = data
        };
    }
}

HttpContext 在 MyService 中应该为 NULL,在 MyMapper 中应该为 NOT NULL,但事实并非如此。请在 MyServiceMyMapper

中查看我的内嵌注释

最佳答案

你把它倒过来了。 HttpContext.Current 将在上下文切换之后为 null,而不是之前。

所以:

// ACTUAL: HttpContext is NOT NULL, WHY?
if(HttpContext.Current == null)
{
    throw new ArgumentNullException("context");
}

不,预期不是null,因为到目前为止还没有任何await(父await 不适用)。

// EXPECTED:  HttpContext should NOT NULL here since async call is already done.
// ACTUAL: HttpContext is NULL here. WHY?
if (HttpContext.Current == null)

切换发生在这一行之后

var response = await client.GetAsync("http://url").ConfigureAwait(false);

所以它应该是null

关于c# - ConfigureAwait(false) 没有按预期使 HttpContext NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49780873/

相关文章:

javascript - 我可以从 mvc 中的一个操作方法一次返回两个结果吗?

c# - 为什么 Path.Combine 没有合并路径和文件?

c# - ASP.NET Core DI 构造函数与 RequestServices

c# - 每天在特定时间在 Web 服务上运行预定进程

c# - 在 Windows 窗体中移动图形

.net HttpWebRequest url 参数中的 URL 编码

.net - 创建到 MySQL 的只读连接?

c# - 使用多少位数字来得出 Math.Round 答案?

c# - 用于查找完整文本并插入空格的正则表达式

c# - 没有编码的 ASP.NET MVC Razor 渲染