web-dev-qa-db-fra.com

Pourquoi HttpContext.Current est null après wait?

J'ai le code de test WebAPI suivant, je n'utilise pas WebAPI en production, mais je l'ai fait à cause d'une discussion que j'ai eu sur cette question: question WebAPI Async

Quoi qu'il en soit, voici la méthode WebAPI incriminée:

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";
}

J'avais cru croire que la deuxième exception était attendue car lorsque le await sera terminé, ce sera probablement sur un autre thread où HttpContext.Current en tant que variable statique de thread ne sera plus résolu à la valeur appropriée. Maintenant, en fonction du contexte de synchronisation, il pourrait en fait être forcé de revenir au même fil après l'attente, mais je ne fais rien de fantaisiste dans mon test. Ceci est juste une utilisation simple et naïve de await.

Dans les commentaires d'une autre question, on m'a dit que HttpContext.Current devrait être résolu après une attente. Il y a même un autre commentaire sur cette question qui indique la même chose. Alors qu'est-ce qui est vrai? Devrait-il résoudre? Je pense que non, mais je veux une réponse qui fasse autorité car async et await sont suffisamment nouveaux pour que je ne trouve rien de définitif.

TL; DR: Is HttpContext.Current _ potentiellement null après un await?

79
welegan

Assurez-vous d’écrire une application ASP.NET 4.5 et de cibler 4,5. async et await ont un comportement non défini sur ASP.NET sauf si vous exécutez la version 4.5 et utilisez le nouveau " "synchronisation conviviale".

Cela signifie notamment que vous devez soit:

  • Ensemble httpRuntime.targetFramework à 4.5, ou
  • Dans votre appSettings, définissez aspnet:UseTaskFriendlySynchronizationContext à true.

Plus d'informations sont disponible ici .

126
Stephen Cleary

Comme @StephenCleary l’a correctement souligné, vous en avez besoin dans votre fichier web.config:

<httpRuntime targetFramework="4.5" />

Lorsque je tentais de résoudre ce problème pour la première fois, j’ai effectué une recherche à l’échelle de la solution à l’échelle de la solution, confirmé que celle-ci était présente dans tous mes projets Web et l’a rapidement écartée. Finalement, j'ai eu l'idée de regarder ces résultats de recherche dans leur contexte complet:

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

Leçon: Si vous mettez à niveau un projet Web vers la version 4.5, vous devez toujours définir ce paramètre manuellement.

22
Todd Menier

Mon test est-il défectueux ou existe-t-il un élément web.config qui fait défaut ici qui permettrait à HttpContext.Current de se résoudre correctement après une attente?

Votre test n'est pas défectueux et HttpContext.Current ne doit pas être nul après l'attente car, dans l'API Web ASP.NET, l'attente garantira que le code qui suit cette attente reçoit le bon HttpContext présent avant l'attente.

3
Darin Dimitrov