web-dev-qa-db-ja.com

C#のコンソールアプリで非同期ですか?

私はこの簡単なコードを持っています:

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

すばらしいです。これがコンパイルされます。

しかし、私はコンソールアプリを持っていて、上記のコードを実行したいとします(SumTwoOperationsAsync()を呼び出します)

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

しかし、私はそれを読んだ(syncを使用するとき)私はすべての方法で同期する必要がありますpdown

質問:つまり、これはMain関数をasyncとしてマークする必要があるということですか?

まあそれはできませんコンパイルエラーがあるからです:

エントリポイントを「async」修飾子でマークすることはできません

非同期のものを理解している場合、スレッドはMain関数に入ります----> SumTwoOperationsAsync ---->両方の関数を呼び出して、アウトになります。しかし、SumTwoOperationsAsyncまで

私は何が欠けていますか?

164
Royi Namir

ほとんどのプロジェクトタイプでは、asyncの "up"および "down"は、async voidイベントハンドラーで終了するか、フレームワークにTaskを返します。

ただし、コンソールアプリはこれをサポートしていません。

返されたタスクに対してWaitを実行するだけです:

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

static async Task MainAsync()
{
  ...
}

または 私が書いたような独自のコンテキストを使用

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

static async Task MainAsync()
{
  ...
}

async Consoleアプリの詳細は 私のブログ です。

272
Stephen Cleary

これを行う最も簡単な方法は次のとおりです

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

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

迅速かつ非常に範囲の広いソリューションとして:

Task.Result

Task.ResultとTask.Waitの両方では、I/Oを使用する場合、I/Oが終了するのを待っている呼び出しスレッドがブロックされたままになるため、スケーラビリティを改善できません。

不完全なタスクで.Resultを呼び出すと、メソッドを実行するスレッドは座ってタスクの完了を待機する必要があり、その間スレッドは他の有用な作業を実行できなくなります。これは、タスクの非同期性の利点を無効にします。

notasync

3
Alberto

私の解決策。 JSONServerは、コンソールウィンドウでHttpListenerサーバーを実行するために作成したクラスです。

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