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

问题描述:

我目前正在编写一个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 
} 
+0

谢谢!这是有道理的,并且完美...比console.read更好! – Andrew 2010-10-01 15:56:58

+0

我也发现这在使用长时间运行的'Task'作为主要工作者来调试Windows服务时很有用。在'Program.Main()'中,使用'#if DEBUG [debug hook] #else [正常服务代码]#endif'等预处理器指令然后在“调试钩子”中,我只需将一个调用添加到'resetEvent .WaitOne()'在new MyService()。OnStart()'后。然后,您可以使用VS调试以调试模式持续运行,而无需以任何有意义的方式修改实际的服务代码。 – 2016-01-27 14:41:41

+0

你是一个frick天才!谢谢! – 2016-06-22 16:19:05

如果这是你所有的应用程序在做,我会建议留出异步调用;你专门想要应用程序'挂起',直到下载完成,所以使用异步操作是违背你想在这里,特别是在一个控制台的应用程序。

+0

我在问题解释中遗漏了这一点,但在下载过程中,我向控制台窗口显示了一个进度指示器。我们正在谈论成千上万的图像,所以最终用户知道发生了什么会很有价值。 – Andrew 2010-10-01 15:51:39

+0

这很好;您仍然可以从同一个线程更新控制台;用户只能用Control-C无法做任何事情,但无论如何,这就是您正在寻找的行为。 – 2010-10-01 15:54:43

+2

使用异步也可以是有益的,如果你需要扩展这个下载多个文件,等等......不知道这里的基本原理,但如果它只是一个文件,同步会更容易.. – 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()?

+2

不错,简单,正是我在找的东西。 – 2013-02-11 17:14:42