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
?
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éfinissezaspnet:UseTaskFriendlySynchronizationContext
àtrue
.
Plus d'informations sont disponible ici .
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.
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.