控制台应用程序在异步呼叫完成之前终止
我目前正在编写一个C#控制台应用程序,该应用程序生成一些指向网站上不同图像的URL,然后使用WebClient.DownloadDataAsync()
以字节流的形式下载。控制台应用程序在异步呼叫完成之前终止
我的问题是,一旦进行了第一次异步调用,控制台应用程序就会认为程序要在异步调用返回之前完成并终止。通过使用Console.Read()
,我可以强制控制台保持打开状态,但这看起来不是很好的设计。此外,如果用户在进程中输入内容(当控制台正在等待输入时),程序将终止。
有没有更好的方法来阻止控制台关闭,而我正在等待异步调用返回?
编辑:调用是异步的,因为我在下载时通过控制台向用户提供状态指示符。
是的。使用ManualResetEvent,并有异步回调呼叫event.Set()
。如果Main例程在3210上阻塞,它将不会退出,直到异步代码完成。
基本的伪代码如下所示:
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
}
如果这是你所有的应用程序在做,我会建议留出异步调用;你专门想要应用程序'挂起',直到下载完成,所以使用异步操作是违背你想在这里,特别是在一个控制台的应用程序。
我在问题解释中遗漏了这一点,但在下载过程中,我向控制台窗口显示了一个进度指示器。我们正在谈论成千上万的图像,所以最终用户知道发生了什么会很有价值。 – Andrew 2010-10-01 15:51:39
这很好;您仍然可以从同一个线程更新控制台;用户只能用Control-C无法做任何事情,但无论如何,这就是您正在寻找的行为。 – 2010-10-01 15:54:43
使用异步也可以是有益的,如果你需要扩展这个下载多个文件,等等......不知道这里的基本原理,但如果它只是一个文件,同步会更容易.. – 2010-10-01 15:57:49
另一种选择是调用异步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()?
不错,简单,正是我在找的东西。 – 2013-02-11 17:14:42
谢谢!这是有道理的,并且完美...比console.read更好! – Andrew 2010-10-01 15:56:58
我也发现这在使用长时间运行的'Task'作为主要工作者来调试Windows服务时很有用。在'Program.Main()'中,使用'#if DEBUG [debug hook] #else [正常服务代码]#endif'等预处理器指令然后在“调试钩子”中,我只需将一个调用添加到'resetEvent .WaitOne()'在new MyService()。OnStart()'后。然后,您可以使用VS调试以调试模式持续运行,而无需以任何有意义的方式修改实际的服务代码。 – 2016-01-27 14:41:41
你是一个frick天才!谢谢! – 2016-06-22 16:19:05