Почему HttpContext.Current null после ожидания?

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

В любом случае, здесь оскорбительный метод 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 достаточно новые, что я не могу найти ничего определенного.

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

Ответ 1

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

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

  • Установите httpRuntime.targetFramework в 4.5 или
  • В вашем appSettings установите aspnet:UseTaskFriendlySynchronizationContext в true.

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

Ответ 2

Поскольку @StephenCleary правильно указал, вам это нужно в вашем web.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, вам все равно нужно установить эту настройку вручную.

Ответ 3

Я ошибаюсь в своем тестировании, или есть какой-то элемент web.config, который мне не хватает здесь это приведет к правильному разрешению HttpContext.Current после ждут?

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