2

Dans mon application ASP.NET Core, j'ai une action apparemment très simple. Il attend une valeur à partir d'une méthode asynchrone, puis retourne comme OK résultat:Strange situation de blocage dans ASP.NET Core Controller

public async Task<IActionResult> GetNextCommand() 
{ 
    var command = await LongPollManager.Instance.GetNextCommand(HttpContext.RequestAborted); 
    return Ok(command); 
} 

Quand j'appelle cette route avec un certain client HTTP je peux vérifier dans le débogueur que cette méthode asynchrone retourne la valeur souhaitée et passe à la méthode Ok:

enter image description here

Si je laisse le débogueur continuer j'attendre pour obtenir le résultat dans mon client HTTP. Mais le client ne reçoit jamais de réponse.

Lorsque je brise ensuite le débogueur, je peux voir que le thread est bloqué sur un verrou interne. Vous pouvez le voir dans la capture d'écran actuelle:

enter image description here

Ce comportement peut être vu que depuis que je fait quelques changements dans ma LongPollManager classe (qui est en fait assez complexe et utilise TaskCompletionSource s et ConcurrentDictionarie s, et SemaphoreSlim s intérieurement). Ce qui me laisse perplexe, c'est que ce n'est pas ma méthode GetNextCommand qui bloque, mais le blocage semble se produire dans ASP.NET Core. Une fois que l'exécution est à la ligne 29 et j'ai reçu mon objet command, tous les trucs asynchrones compliqués de ma classe LongPollManager sont terminés et je ne vois pas comment tout ce que je change dans LongPollManager peut empêcher ASP.NET Core de terminer correctement la requête.

Que peut-on attendre d'ASP.NET Core? Comment mon code (qui court vers la ligne 29 sans blocage) peut-il provoquer une telle situation de blocage?

+0

Comment le client appelle-t-il – Nkosi

+0

Le client est un autre processus sur la même machine effectuant un HTTP GET sur cette route. –

+2

Le modèle renvoyé est-il un objet POCO ou des effets d'invocation sont-ils invoqués lors de la sérialisation? – Nkosi

Répondre

3

Comme mentionné dans les commentaires

Mais avec mes dernières modifications, il contient également une propriété Task publique. Pensez-vous que cela pourrait avoir des effets secondaires lorsque ASP.NET Core tente de le sérialiser?

Oui, il le fera.

Le framework essaiera d'appeler la propriété pour obtenir la valeur de la sérialisation. Et comme la propriété renvoie un Task, essaiera probablement de sérialiser la propriété .Result de la tâche de manière synchrone, ce qui conduirait à votre verrou mort.

Le mélange d'appels asynchrones et de blocage comme .Result et .Wait() peut provoquer des blocages et doit être évité.

Référence Async/Await - Best Practices in Asynchronous Programming

Les actions doivent retourner Poços simples qui ont pas d'effets secondaires lorsqu'ils sont sérialisés.

La propriété Task publique doit être masquée dans le programme de formation, ignorée via les attributs ou doit être convertie en méthodes qui ne sont pas appelées lorsque le modèle est sérialisé.