web-dev-qa-db-fra.com

Async à l'application de la console en C #?

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 ?

166
Royi Namir

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 .

279
Stephen Cleary

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 ...
}
90

En tant que solution rapide et très étendue:

Task.Result

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.

notasync

3
Alberto

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);

    }
}
1
Richard Keene