Почему HttpContext.Текущий null после ожидания?


у меня есть следующий тестовый код WebAPI, я не использую WebAPI в производстве, но я сделал это из-за обсуждения, которое у меня было по этому вопросу: WebAPI Async question

в любом случае, вот оскорбительный метод WebAPI:

public async Task<string> Get(int id)
{
    var x = HttpContext.Current;
    if (x == null)
    {
        // not thrown
        throw new ArgumentException("HttpContext.Current is null");
    }

    await Task.Run(() => { Task.Delay(500); id = 3; });

    x = HttpContext.Current;
    if (x == null)
    {
        // thrown
        throw new ArgumentException("HttpContext.Current is null");
    }

    return "value";
}

Я до сих пор считал, что второе исключение ожидается, потому что когда await завершается, скорее всего, это будет в другом потоке, где HttpContext.Current как потоковая статическая переменная больше не будет разрешаться до соответствующего значения. Сейчас, основываясь на контексте синхронизации, он действительно может быть вынужден вернуться к тому же потоку после ожидания, но я не делаю ничего необычного в своем тесте. Это просто простое, наивное использование await.

в комментариях в другом вопросе мне сказали, что HttpContext.Current должен решить после ожидания. Есть даже еще один комментарий по этому вопросу, указывающий на то же самое. Так что же правда? Должен ли он разрешиться? Я думаю, что нет, но я хочу авторитетный ответ на это, потому что async и await is достаточно новый, что я не могу найти ничего определенного.

TL; DR: Is HttpContext.Current потенциально null после await?

3 72

3 ответа:

пожалуйста, убедитесь, что вы пишете ASP.NET 4.5 применение и таргетинг 4.5. async и await имеют неопределенное поведение на ASP.NET если вы не работаете на 4.5 и используют новый" удобный для задач " контекст синхронизации.

в частности, это означает, что вы должны:

  • Set httpRuntime.targetFramework до 4.5 или
  • в своем appSettings, set aspnet:UseTaskFriendlySynchronizationContext до true.

более подробная информация здесь.

Как правильно указал @StephenCleary, вам это нужно в вашем интернете.config:

<httpRuntime targetFramework="4.5" />

когда я впервые устранял эту проблему, я сделал поиск по всему решению для вышеизложенного, подтвердил, что он присутствует во всех моих веб-проектах и быстро отклонил его как виновника. В конце концов мне пришло в голову посмотреть эти результаты поиска в полном контексте:

<!--
  For a description of web.config changes for .NET 4.5 see http://go.microsoft.com/fwlink/?LinkId=235367.

  The following attributes can be set on the <httpRuntime> tag.
    <system.Web>
      <httpRuntime targetFramework="4.5" />
    </system.Web>
-->

Doh.

урок: если вы обновляете веб-проект до 4.5, вам все равно нужно получить эту настройку место вручную.

мой тест испорчен, или есть какая-то сеть.элемент конфигурации мне не хватает вот что бы сделать HttpContext.Текущее решение правильно после ждать?

ваш тест не является ошибочным и HttpContext.Current не должен быть null после ожидания, потому что в ASP.NET веб-API когда вы ждете, это гарантирует, что код, следующий за этим ожиданием, будет передан правильный HttpContext, который присутствовал перед ожиданием.