Console.ReadLine 不处理任务的 ContinueWith
Console.ReadLine not working on Task's ContinueWith
假设我有这段代码:
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)
相反,它不会等待任何输入,控制台应用程序会立即关闭。
如果我在 ContinueWith
中执行它,为什么 Console.ReadLine()
不起作用?
在您的第一个示例中,它不是 Task.WhenAll(tasks)
,而是 Console.ReadLine()
等待回调 Task
完成。方法 WhenAll()
不会等待 .ContinueWith()
,因为它是 tasks
数组中不存在的单独任务。
在你的第二种情况下 WhenAll
等待两个任务完成,但是当它们完成时你的程序完成执行。
不要忘记,如果您异步执行 Console.ReadLine()
,它会阻塞执行它的 Thread
,而且这次它不是主线程。它也不会被等待,如果在你的第二种情况下你将添加 Thread.Sleep(5000);
到 Main
方法的末尾,它会等待 5 秒允许用户输入文本,但无论事实是否如此,它都会完成或者用户没有按下 'enter'.
不等待 ReadLine 的简短示例:
static void Main(string[] args)
{
Task t = new Task(() => { Console.ReadLine(); Console.WriteLine("You pressed enter"); });
t.Start();
Thread.Sleep(5000);
}
//只执行5秒
ContinueWith
创建了一个新的任务,你也需要等待,所以在它后面添加一个Wait
就可以了。
var tasks = new Task<string>[] { ToStringAsync(1) };
Task.WhenAll(tasks)
.ContinueWith(r =>
{
Console.WriteLine(r.Result.First());
Console.ReadLine();
})
.Wait();
现在主线程将在结束程序之前等待继续完成。
当 ReadLine
在延续之外时它 "works" 的原因是因为它阻塞了主线程,但你可能会足够快地按下回车,它仍然会在之前结束程序WriteLine
的发生取决于 tasks
花费的时间。
假设我有这段代码:
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)
相反,它不会等待任何输入,控制台应用程序会立即关闭。
如果我在 ContinueWith
中执行它,为什么 Console.ReadLine()
不起作用?
在您的第一个示例中,它不是 Task.WhenAll(tasks)
,而是 Console.ReadLine()
等待回调 Task
完成。方法 WhenAll()
不会等待 .ContinueWith()
,因为它是 tasks
数组中不存在的单独任务。
在你的第二种情况下 WhenAll
等待两个任务完成,但是当它们完成时你的程序完成执行。
不要忘记,如果您异步执行 Console.ReadLine()
,它会阻塞执行它的 Thread
,而且这次它不是主线程。它也不会被等待,如果在你的第二种情况下你将添加 Thread.Sleep(5000);
到 Main
方法的末尾,它会等待 5 秒允许用户输入文本,但无论事实是否如此,它都会完成或者用户没有按下 'enter'.
不等待 ReadLine 的简短示例:
static void Main(string[] args)
{
Task t = new Task(() => { Console.ReadLine(); Console.WriteLine("You pressed enter"); });
t.Start();
Thread.Sleep(5000);
}
//只执行5秒
ContinueWith
创建了一个新的任务,你也需要等待,所以在它后面添加一个Wait
就可以了。
var tasks = new Task<string>[] { ToStringAsync(1) };
Task.WhenAll(tasks)
.ContinueWith(r =>
{
Console.WriteLine(r.Result.First());
Console.ReadLine();
})
.Wait();
现在主线程将在结束程序之前等待继续完成。
当 ReadLine
在延续之外时它 "works" 的原因是因为它阻塞了主线程,但你可能会足够快地按下回车,它仍然会在之前结束程序WriteLine
的发生取决于 tasks
花费的时间。