Source::https://note.guoqianfan.com/2022/04/23/dont-use-async-void/
Préface
Je l'ai vu dans le document.:Sauf quewinformLes événements dePeut être utiliséasync void,Autres casAbsolument pasUtiliserasync void,C'est de l'utiliser.async Task.
Pour cette spécification,Bien que je ne comprenne pas très bien pourquoi Nelly,Mais il l'a toujours fait..
Jusqu'à ce jour, j'ai vu ce blog:In ASP.NET Core Utilisation abusive async void Ça a commencé. 502(Bad Gateway),Dis - le.async voidUne exception peut causer un crash du programme.L'étude a testé,J'ai enfin compris pourquoi..
Les points saillants de l'extrait sont les suivants::
Selon un autre indice fourni par l'utilisateur 「 Une fonction du site Web est cassée 」, On continue à chercher , J'a i vu une nouvelle méthode récemment ajoutée au Code ,Il a utilisé async void,C'est vrai,Il a utilisé async void, Et malheureusement, ça arrive Exception, Le pire, c'est que Exception Non traité .
C'est vrai. C# Un ami qui connaît la programmation asynchrone , En regardant de ce côté, vous devriez savoir ce qui s'est passé ,async void Est la façon dont il est recommandé d'éviter l'utilisation de déclarations , Une des raisons est quand async void La méthode se produit Exception Impossible de capturer à partir de l'appelant ,Même avec try...catch... Ça n'aide pas non plus ,async void C'est un peu comme si on en avait un autre Thread Pour exécuter le programme , Si cela se produit pendant l'exécution Exception Je ne m'en suis pas occupé ,Exception Et ils seront jetés jusqu'au bout , En fin de compte, AppDomain La hiérarchie est saisie , Et puis notre application est suspendue .
async-void-L'exception à la méthode ne peut pas être saisie
async voidException lancée par la méthode Impossible de capturer , L'anomalie sera jetée tout le temps ,En fin de compte,AppDomain La hiérarchie est saisie , Et le programme est suspendu .
Voici un exemple de code::
[HttpGet]
public async void Get()
{
try
{
ThrowExceptionAsync();
}
catch (Exception ex)
{
// Aucune exception ne peut être saisie ici ,Crash du programme!
_logger.LogInformation(ex, "ex...");
}
}
async void ThrowExceptionAsync()
{
throw new Exception("async void ex!");
}
Attention!
Ce qui précède est async void Exception inattendue lancée par la méthode .Inasync voidMéthode interne,Nous pouvons encore utilisertry catch, La logique est la logique normale . Voir l'exemple ci - dessous pour plus de détails :
[HttpGet]
public async void Get()
{
//Inasync voidMéthode interne,Nous pouvons encore utilisertry catch, La logique est la logique normale .
//Ici.try catchÇa marche.. Exception prise en charge ,async void Aucune exception à l'exécution de la méthode , Ne provoque pas l'écrasement du programme .
try
{
await Task.Run(() =>
{
throw new Exception("ex!");
});
}
catch (Exception ex)
{
_logger.LogInformation(ex,"ex...");
}
}
Tests
Crash
Le Code qui peut causer un crash en cas d'exception est 2Espèce,Comme suit:
[HttpGet]
public async void Get()
{
// Une exception peut entraîner un crash du programme
throw new Exception("ex!");
}
[HttpGet]
public async void Get()
{
// Une exception peut entraîner un crash du programme
await Task.Run(() =>
{
throw new Exception("ex!");
});
}
Attention!
En bas.async void Le Code ne lance pas d'exception .
[HttpGet]
public async void Get()
{
Task.Run(() =>
{
throw new Exception("ex!");
});
}
Dans le Codeasync voidPas de problème!(Ne pas lancer d'exception), En fait, c'est logique .Parce queasync voidÀ l'intérieurAucune anomalie, Naturellement, il n'y a pas de crash de programme .
L'anomalie estTask.RunÀ l'intérieur,Parce queNon utiliséawaitAttendez., Alors l'anomalie est Threadpool threadCapturé, Quand ils ont été capturés , Il ne sera plus jeté là - haut , Directement digéré à l'intérieur .
Parce queasync voidAu moment de l'exécutionAucune anomalie, Naturellement, il n'y a pas de crash de programme .
Mais comme nous ne pouvons pas garantir qu'il n'y a pas d'exception dans tout le Code ,Alors...Non, non.Utiliserasync void!
Pas de crash
Tant queNon, pas du tout.async void, Même si le gestionnaire de requêtes lance une exception ,Et ça n'affectera pasLe fil principalDe. Tout au plus, cette requête a mal tourné ,Retour500 Internal Server ErrorC'est juste.
Voici quelques codes testés :
[HttpGet]
public async Task Get()
{
//500Code d'erreur
throw new Exception("ex!");
}
[HttpGet]
public async Task Get()
{
//500Code d'erreur
await Task.Run(() =>
{
throw new Exception("ex!");
});
}








