J'ai ce code simple:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Génial. cela compile.
Mais disons que j'ai une application console et que je veux exécuter le code ci-dessus (appelant SumTwoOperationsAsync()
)
static void Main(string[] args)
{
SumTwoOperationsAsync();
}
Mais j'ai lu que (lorsque j'utilise sync
), je dois synchroniser complètement p et down:
Question: Cela signifie-t-il que ma fonction Main
doit être marquée comme async
?
Eh bien c'est ne peut pas être parce qu'il y a une erreur de compilation:
un point d'entrée ne peut pas être marqué avec le modificateur 'async'
Si je comprends la situation asynchrone, le fil entrera dans la fonction Main
---- ---- _ SumTwoOperationsAsync
----> appellera les deux fonctions et sortira . mais jusqu'à ce que SumTwoOperationsAsync
Qu'est-ce que je rate ?
Dans la plupart des types de projets, votre async
"up" et "down" se termineront par un gestionnaire d'événement async void
ou renverront un Task
dans votre framework.
Cependant, les applications de la console ne supportent pas cela.
Vous pouvez soit simplement faire un Wait
sur la tâche retournée:
static void Main()
{
MainAsync().Wait();
// or, if you want to avoid exceptions being wrapped into AggregateException:
// MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
...
}
ou vous pouvez tilisez votre propre contexte comme celui que j'ai écrit :
static void Main()
{
AsyncContext.Run(() => MainAsync());
}
static async Task MainAsync()
{
...
}
Plus d'informations pour async
Console apps est sur mon blog .
Voici le moyen le plus simple de le faire
static void Main(string[] args)
{
Task t = MainAsync(args);
t.Wait();
}
static async Task MainAsync(string[] args)
{
await ...
}
En tant que solution rapide et très étendue:
Task.Result et Task.Wait ne permettent pas d'améliorer l'évolutivité lorsqu'elles sont utilisées avec des E/S, car elles entraîneront le blocage du thread appelant en attente de la fin des E/S.
Lorsque vous appelez .Result sur une tâche incomplète, le thread qui exécute la méthode doit attendre que la tâche soit terminée, ce qui l'empêche de faire tout autre travail utile entre-temps. Cela annule l'avantage de la nature asynchrone de la tâche.
Ma solution JSONServer est une classe que j'ai écrite pour exécuter un serveur HttpListener dans une fenêtre de console.
class Program
{
public static JSONServer srv = null;
static void Main(string[] args)
{
Console.WriteLine("NLPS Core Server");
srv = new JSONServer(100);
srv.Start();
InputLoopProcessor();
while(srv.IsRunning)
{
Thread.Sleep(250);
}
}
private static async Task InputLoopProcessor()
{
string line = "";
Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);
while(line != "quit")
{
Console.Write(": ");
line = Console.ReadLine().ToLower();
Console.WriteLine(line);
if(line == "?" || line == "help")
{
Console.WriteLine("Core NLPS Server Help");
Console.WriteLine(" ? or help: Show this help.");
Console.WriteLine(" quit: Stop the server.");
}
}
srv.Stop();
Console.WriteLine("Core Processor done at " + DateTime.Now);
}
}