Dlaczego jest HttpContext.Aktualne null po oczekiwaniu?

Mam następujący testowy kod WebAPI, nie używam WebAPI w produkcji, ale zrobiłem to z powodu dyskusji, którą miałem na to pytanie: WebAPI async pytanie

Tak czy inaczej, oto metoda 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";
}

Wierzyłem, że drugi wyjątek jest oczekiwany, ponieważ gdy await zakończy się, prawdopodobnie będzie na innym wątku, gdzie {[2] } jako zmienna statyczna wątku nie będzie już rozwiązywać do odpowiedniej wartości. Teraz, na podstawie kontekst synchronizacji, faktycznie może być zmuszony do powrotu do tego samego wątku po oczekiwaniu, ale nie robię nic fantazyjnego w moim teście. Jest to po prostu proste, naiwne użycie await.

W komentarzach do innego pytania powiedziano mi, że HttpContext.Current powinno się rozwiązać po oczekiwaniu. Jest jeszcze jeden komentarz na to pytanie, wskazujący na to samo. Więc co jest prawdą? Czy powinno się rozwiązać? Myślę, że nie, ale chcę autorytatywnej odpowiedzi na to, ponieważ async i await jest na tyle Nowa, że nie mogę znaleźć cokolwiek definitywnego.

TL;DR: czy HttpContext.Current potencjalnie null po await?

Author: Dr Rob Lang, 2013-08-22

3 answers

Upewnij się, że piszesz ASP.NET 4.5 aplikacji, a kierowanie 4.5. async i await mają nieokreślone zachowanie na ASP.NET chyba że używasz 4.5 i używasz nowego kontekstu synchronizacji "przyjaznego dla zadań".

W szczególności oznacza to, że musisz:

  • Ustaw httpRuntime.targetFramework na 4.5, lub
  • w Twoim appSettings Ustaw aspnet:UseTaskFriendlySynchronizationContext na true.

Więcej informacji jest dostępne tutaj .

 116
Author: Stephen Cleary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-23 11:22:08

Jak słusznie zauważył @ StephenCleary, potrzebujesz tego w swojej sieci.config:

<httpRuntime targetFramework="4.5" />

Kiedy po raz pierwszy rozwiązywałem ten problem, przeprowadziłem szeroko zakrojone poszukiwania powyższego rozwiązania, potwierdziłem, że jest on obecny we wszystkich moich projektach internetowych i szybko odrzuciłem go jako winowajcę. W końcu przyszło mi do głowy, aby spojrzeć na te wyniki wyszukiwania w pełnym kontekście:

<!--
  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.

Lekcja: jeśli zaktualizujesz projekt sieci web do wersji 4.5, nadal musisz ręcznie wprowadzić to ustawienie.

 18
Author: Todd Menier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-28 18:16:31

Czy mój test jest wadliwy, Czy jest jakaś sieć.brakuje mi elementu config tutaj zrobiłby HttpContext.Aktualne rozwiązanie poprawnie po czekać?

Twój test nie jest wadliwy i HttpContext.Current nie powinien być null po oczekiwaniu, ponieważ w ASP.NET Web API kiedy czekasz, zapewni to, że kod następujący po tym oczekiwaniu zostanie przekazany poprawnemu Httpcontextowi, który był obecny przed czekaniem.

 3
Author: Darin Dimitrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-22 15:13:42