控制台应用在异步呼叫完成之前终止

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了控制台应用在异步呼叫完成之前终止相关的知识,希望对你有一定的参考价值。

我目前正在编写一个C#控制台应用程序,它会生成许多指向网站上不同图像的URL,然后使用WebClient.DownloadDataAsync()作为字节流下载。

我的问题是,一旦进行了第一次异步调用,控制台应用程序会认为程序已完成并在异步调用返回之前终止。通过使用Console.Read()我可以强制控制台保持打开,但这似乎不是很好的设计。此外,如果用户在进程期间点击进入(当控制台正在等待输入时),程序将终止。

在等待异步调用返回时,是否有更好的方法可以阻止控制台关闭?

编辑:调用是异步的,因为我在下载过程中通过控制台向用户提供状态指示器。

答案

是。使用ManualResetEvent,并使用异步回调调用event.Set()。如果Main例程在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
}
另一答案

另一个选择是只调用异步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();
}

What is the difference between .Wait() vs .GetAwaiter().GetResult()?

另一答案

如果这是您的所有应用程序正在进行的操作,我建议不要进行异步调用;您特别希望应用程序在下载完成之前“挂起”,因此使用异步操作与此处的操作相反,尤其是在控制台应用程序中。

另一答案

应该说,在C#7.1中,Main现在可以标记为async

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

以上是关于控制台应用在异步呼叫完成之前终止的主要内容,如果未能解决你的问题,请参考以下文章

UCMA 如何在遇忙信号和终止信号之前检测呼叫响铃持续时间并转移呼叫?

WCF服务需要调用异步

将Task变成孤儿有什么缺点吗?

编写异步控制器并更新进度

应用程序在 onStop() 完成之前终止

强制 JVM 在终止之前完成代码块