Завершение консольного приложения перед завершением асинхронного вызова - PullRequest
36 голосов
/ 01 октября 2010

В настоящее время я пишу консольное приложение C #, которое генерирует несколько URL-адресов, которые указывают на разные изображения на веб-сайте, а затем загружает их в виде потоков байтов, используя WebClient.DownloadDataAsync().

Моя проблема заключается в том, что после первого асинхронного вызова консольное приложение считает, что программа завершена, и завершает работу, прежде чем асинхронный вызов может вернуться. Используя Console.Read(), я могу заставить консоль оставаться открытой, но это не очень хороший дизайн. Кроме того, если пользователь нажмет ввод во время процесса (пока консоль ожидает ввода), программа завершится.

Есть ли лучший способ предотвратить закрытие консоли во время ожидания возврата асинхронного вызова?

Изменить: вызовы асинхронные, потому что я предоставляю пользователю индикатор состояния через консоль во время загрузки.

Ответы [ 4 ]

46 голосов
/ 01 октября 2010

Да. Используйте 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
}
26 голосов
/ 29 января 2013

Другой вариант - просто вызвать асинхронный метод 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 ()?

6 голосов
/ 01 октября 2010

Если это все, что делает ваше приложение, я бы предложил исключить асинхронный вызов; вы хотите, чтобы приложение зависало до завершения загрузки, поэтому асинхронная операция противоречит тому, что вы хотите здесь, особенно в консольном приложении.

0 голосов
/ 11 июня 2018

Следует указать, что в C # 7.1 Main теперь можно пометить как async.

static async Task Main()
{
  await LongRunningOperation();
}
...