假设我有这段代码:
var tasks = new Task<string>[] { ToStringAsync(1) };
Task.WhenAll(tasks).ContinueWith(r => Console.WriteLine(r.Result.First()));
Console.ReadLine();
ToStringAsync
具有以下实施方式:
private Task<string> ToStringAsync(object obj)
{
return Task.FromResult(obj != null ? obj.ToString() : null);
}
这很好用,打印出来:
> 1
> _ (Wait for user interaction)
但是,如果我将Console.ReadLine()
移至我的匿名操作:
var tasks = new Task<string>[] { ToStringAsync(1) };
Task.WhenAll(tasks).ContinueWith(r =>
{
Console.WriteLine(r.Result.First());
Console.ReadLine();
});
这应该产生与以前完全相同的输出:
> 1
> _ (Wait for user interaction)
相反,它不会等待任何输入,并且控制台应用程序会立即关闭。
为什么Console.ReadLine()
在ContinueWith
内执行时无法正常工作?
答案 0 :(得分:0)
在您的第一个示例中,它不是Task.WhenAll(tasks)
,而是Console.ReadLine()
等待回调Task
完成。方法WhenAll()
不会等待.ContinueWith()
因为tasks
数组中不存在的单独任务。
在你的第二个场景中WhenAll
等待两个任务完成,但是当你的程序完成执行时。
不要忘记,如果您异步执行Console.ReadLine()
,它会阻止执行它的Thread
,而且它不是主线程这次。它也是等待的,如果在第二种情况下你将Thread.Sleep(5000);
添加到Main
方法的末尾,它会等待5秒钟,允许用户输入文字,但之后就完成了无论用户是否按下&#39;输入&#39;
未等待ReadLine时的简短示例:
static void Main(string[] args)
{
Task t = new Task(() => { Console.ReadLine(); Console.WriteLine("You pressed enter"); });
t.Start();
Thread.Sleep(5000);
}
//仅执行5秒
答案 1 :(得分:0)
ContinueWith
会创建一个您还需要等待的新任务,因此只需在其后添加Wait
即可。
var tasks = new Task<string>[] { ToStringAsync(1) };
Task.WhenAll(tasks)
.ContinueWith(r =>
{
Console.WriteLine(r.Result.First());
Console.ReadLine();
})
.Wait();
现在主线程将在结束程序之前等待继续完成。
当ReadLine
在延续之外时它“工作”的原因是因为它阻塞了主线程,但你可能会足够快地输入,以至于它仍然会在{{1}之前结束程序根据{{1}}占用的时间长短发生。