web-dev-qa-db-ja.com

非同期呼び出しが完了する前にコンソールアプリが終了する

私は現在、Webサイト上のさまざまな画像を指す多数のURLを生成し、WebClient.DownloadDataAsync()を使用してバイトストリームとしてダウンロードするC#コンソールアプリを作成しています。

私の問題は、最初の非同期呼び出しが行われると、コンソールアプリはプログラムが完了したと見なし、非同期呼び出しが戻る前に終了することです。 Console.Read()を使用することで、コンソールを強制的に開いたままにすることができますが、これはあまり良い設計ではないようです。さらに、プロセス中に(コンソールが入力を待機している間に)ユーザーがEnterキーを押すと、プログラムは終了します。

非同期呼び出しが戻るのを待っている間にコンソールが閉じないようにするためのより良い方法はありますか?

編集:ダウンロードが行われている間、コンソールを介してユーザーにステータスインジケーターを提供しているため、呼び出しは非同期です。

37
Andrew Keller

はい。 ManualResetEvent を使用し、非同期コールバックでevent.Set()を呼び出します。メインルーチンがevent.WaitOne()でブロックした場合、非同期コードが完了するまで終了しません。

基本的な擬似コードは次のようになります。

static ManualResetEvent resetEvent = new ManualResetEvent(false);

static void Main()
{
     CallAsyncMethod();
     resetEvent.WaitOne(); // Blocks until "set"
}

void DownloadDataCallback()
{
     // Do your processing on completion...

     resetEvent.Set(); // Allow the program to exit
}
49
Reed Copsey

もう1つのオプションは、非同期Mainメソッドを呼び出して、返されるタスクを待つことです。

_static void Main(string[] args)
{
    MainAsync(args).Wait();
}

static async Task MainAsync(string[] args)
{
    // .. code goes here
}
_

.NET 4.5以降、GetAwaiter().GetResult()を呼び出すことができるようになりました

_static void Main(string[] args)
{
    MainAsync(args).GetAwaiter().GetResult();
}
_

。Wait()と.GetAwaiter()。GetResult()の違いは何ですか?

27

アプリケーションが実行しているのがそれだけの場合は、非同期呼び出しを除外することをお勧めします。具体的にはwantダウンロードが完了するまでアプリを「ハング」させるため、非同期操作の使用は、特にコンソールアプリでは、ここで必要なこととは逆になります。

6
Andrew Barber

C#7.1では、Mainasyncとしてマークできるようになったことを述べておく必要があります。

static async Task Main()
{
  await LongRunningOperation();
}
1
mariocatch