async at console app in C#? [duplicate]

2019-01-01 15:15发布

问题:

This question already has an answer here:

  • Can't specify the 'async' modifier on the 'Main' method of a console app 15 answers

I have this simple code :

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

Great. this compiles.

But Lets say I have a console app and I want to run the code above ( calling SumTwoOperationsAsync())

 static  void Main(string[] args)
        {
             SumTwoOperationsAsync();
        }

But I\'ve read that (when using sync) I have to sync all the way up and down :

Question : So does this means that my Main function should be marked as async ?

Well it can\'t be because there is a compilation error:

an entry point cannot be marked with the \'async\' modifier

If I understand the async stuff , the thread will enter the Main function ----> SumTwoOperationsAsync ---->will call both functions and will be out. but until the SumTwoOperationsAsync

What am I missing ?

回答1:

In most project types, your async \"up\" and \"down\" will end at an async void event handler or returning a Task to your framework.

However, Console apps do not support this.

You can either just do a Wait on the returned task:

static void Main()
{
  MainAsync().Wait();
  // or, if you want to avoid exceptions being wrapped into AggregateException:
  //  MainAsync().GetAwaiter().GetResult();
}

static async Task MainAsync()
{
  ...
}

or you can use your own context like the one I wrote:

static void Main()
{
  AsyncContext.Run(() => MainAsync());
}

static async Task MainAsync()
{
  ...
}

More information for async Console apps is on my blog.



回答2:

Here is the simplest way to do this

static void Main(string[] args)
{
    Task t = MainAsync(args);
    t.Wait();
}

static async Task MainAsync(string[] args)
{
    await ...
}


回答3:

As a quick and very scoped solution:

Task.Result

Both Task.Result and Task.Wait won\'t allow to improving scalability when used with I/O, as they will cause the calling thread to stay blocked waiting for the I/O to end.

When you call .Result on an incomplete Task, the thread executing the method has to sit and wait for the task to complete, which blocks the thread from doing any other useful work in the meantime. This negates the benefit of the asynchronous nature of the task.

notasync



回答4:

My solution. The JSONServer is a class I wrote for running an HttpListener server in a console window.

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

    }
}