我目前正在编写一个C#控制台应用程序,该应用程序生成许多指向网站上不同图像的URL,然后使用WebClient.DownloadDataAsync()
作为字节流下载。
我的问题是,一旦进行了第一次异步调用,控制台应用程序会认为程序已完成并在异步调用返回之前终止。通过使用Console.Read()
,我可以强制控制台保持打开状态,但这似乎不是很好的设计。此外,如果用户在进程中遇到enter(当控制台正在等待输入时),程序将终止。
在等待异步调用返回时,是否有更好的方法可以阻止控制台关闭?
编辑:调用是异步的,因为我在下载过程中通过控制台向用户提供状态指示器。
答案 0 :(得分:46)
是。使用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
}
答案 1 :(得分:25)
另一种选择是只调用异步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()?
答案 2 :(得分:6)
如果这是您的所有应用程序正在执行的操作,我建议不要执行异步调用;你明确地希望应用程序“挂起”直到下载完成,所以使用异步操作与你想要的相反,特别是在控制台应用程序中。
答案 3 :(得分:0)
应该说明在C#7.1 Main
现在可以标记为async
。
static async Task Main()
{
await LongRunningOperation();
}