web-dev-qa-db-fra.com

IWebHost: appel de Run () vs RunAsync ()

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?

9
Ali Zahid

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 de private static void $GeneratedMain() => Main().GetAwaiter().GetResult();
  • static Task Main(string[]) aura pour résultat que le compilateur émettra l'équivalent de private 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).

6
poke

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

1
idubnori