Lorsqu'un nouveau projet ASP.NET Core 2.0 est créé, la méthode boilerplate Main
de la classe Program
ressemble à ceci:
public static void Main(string[] args)
{
BuildWebHost(args).Run(); // BuildWebHost returns an IWebHost
}
Mais depuis C # 7.1, la méthode Main
peut être une méthode asynchrone renvoyant Task
au lieu de void
. Cela signifie qu'il est beaucoup plus facile d'appeler une méthode asynchrone dans Main
.
Ainsi, la RunAsync()
sur IWebHost
peut être appelée dans Main
au lieu de la méthode Run()
. Quelque chose comme ça:
public static async Task Main(string[] args)
{
await BuildWebHost(args).RunAsync().ConfigureAwait(false);
}
Selon la documentation , la méthode Run
:
Exécute une application Web et bloque le thread appelant jusqu'à l'arrêt de l'hôte.
Considérant que la méthode RunAsync
:
Exécute une application Web et renvoie une tâche qui ne se termine que lorsque le jeton est déclenché ou que l'arrêt est déclenché.
Je me demandais quand la méthode RunAsync
devrait-elle être utilisée à la place de la méthode Run
régulière? Quelles sont les implications pratiques de cela? L'utilisateur final remarquerait-il une différence?
Les modèles ASP.NET Core par défaut contiennent la méthode Main
suivante:
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
Cette méthode Run
il existe la méthode d’extension WebHostExtensions.Run
qui est implémentée comme ceci :
public static void Run(this IWebHost Host)
{
Host.RunAsync().GetAwaiter().GetResult();
}
Donc, cela appelle en réalité WebHostExtensions.RunAsync
, et bloque juste dessus.
Voyons maintenant comment la méthode asynchrone Main
de C # 7.1 est spécifiée :
Lorsque l'une de [ces méthodes basées sur des tâches] est identifiée comme point d'entrée, le compilateur synthétise une méthode de point d'entrée réelle qui appelle l'une de ces méthodes codées:
static Task Main()
aura pour résultat que le compilateur émettra l'équivalent deprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task Main(string[])
aura pour résultat que le compilateur émettra l'équivalent deprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
Donc, fondamentalement, avoir une méthode asynchrone Main
comme celle-ci:
public static async Task Main(string[] args)
{
await BuildWebHost(args).RunAsync();
}
Le compilateur émettra également les éléments suivants:
private static void $GeneratedMain(string[] args)
{
Main(args).GetAwaiter().GetResult();
}
Et si vous regardez de près ce qui se passe avec la tâche retournée ici, c'est quasiment la même chose que ce que fait la méthode WebHostExtensions.Run
.
Qu'est-ce que cela signifie? Vous pouvez utiliser l'une de ces solutions et l'effet sera le même. Votre application bloquera correctement jusqu'à ce que la tâche asynchrone soit résolue. Il n'y a pas de différence pratique entre les solutions. Le seul avantage réel que vous aurait à utiliser une méthode principale asynchrone serait si vous aviez un travail asynchrone à effectuer dans la méthode Main
; bien que ce soit probablement un cas très rare car, pour les applications Web, vous êtes plus susceptible de travailler dans le cycle de vie de l’application ASP.NET Core (c'est-à-dire dans Startup
et non en dehors de celle-ci).
Quelles sont les implications pratiques de cela? L'utilisateur final remarquera-t-il Une différence?
Il n'y a pas de différence sur le comportement de niveau RunTime.
Puisque cette fonctionnalité ne correspond pas à un changement de code CLR, la méthode async. Main est simplement un sucre syntaxique . Cette conception permet la compatibilité de backend Avec les versions précédentes. Pour plus de détails sur , veuillez vous reporter à Async Main dans le dépôt Roslyn Git.} _
- C # 7 Série, Partie 2: Async Main