C# 使用Task.Run()写入控制台失败
我的一位同事发现我们的代码有一个问题,花了一段时间才找到到底发生了什么,但下面这个简单的例子可以最好地说明这一点:C# 使用Task.Run()写入控制台失败,c#,.net-4.5,C#,.net 4.5,我的一位同事发现我们的代码有一个问题,花了一段时间才找到到底发生了什么,但下面这个简单的例子可以最好地说明这一点: // Fails class Program { static void Main(string[] args) { Task.Run(() => Console.WriteLine("Hello World")); Console.ReadKey(); } } // Works fine class Program
// Fails
class Program
{
static void Main(string[] args)
{
Task.Run(() => Console.WriteLine("Hello World"));
Console.ReadKey();
}
}
// Works fine
class Program
{
static void Main(string[] args)
{
Console.Write(String.Empty);
Task.Run(() => Console.WriteLine("Hello World"));
Console.ReadKey();
}
}
很明显,从主线程到控制台的任何地方写入都会允许后台线程也写入控制台,但是我们很难理解为什么会发生这种情况。有人能解释一下,从主线程写入控制台时,第一个代码段没有实现什么吗?事实上,第一个案例没有失败。“Hello World”出现在应用程序结束之前。这是一本经典的书。在第一种情况下,来自主线程的
Console.ReadKey()
击败了任务,在第二种情况下,任务获胜。不幸的是,我不能确切地告诉您为什么写空字符串会使任务成功。我怀疑发生了什么。我观察到:
- 如果在启动
之前对控制台的输出执行任何操作,都可以。这包括获取ReadKey
,但不使用它控制台.Out
- 如果在
调用开始之前延迟Console.WriteLine
调用,则没有问题(在Console.ReadKey
等待时,您可以有多个ReadKey
调用)WriteLine
ReadKey
方法会一直保持锁,直到一个键被读取为止。这当然可以解释到目前为止我运行的每个程序
虽然执行假设初始化的操作很有趣-读取Console.Out
“修复”了问题,但从Console.In
读取则没有
我怀疑ReadKey
初始化了输出,因为该值仍会回显到控制台…但我不想发誓
有趣的是,使用
Console.ReadLine()
而不是Console.ReadKey()
一开始并不会导致问题。您没有描述失败案例中会发生什么。在我的框中,它似乎会一直挂起,直到您点击回车键,然后打印出来。@jonsket是的,这就是我看到的行为。这确实是解决方案。我认为这不对。它不像调用Console.WriteLine之后发生的那样对Console.ReadLine的调用已完成-否则,如果您等待一段时间,您将看到输出。我认为这似乎是某种初始化问题。或者更清楚地说-我相信这是一种竞争条件,但仅限于哪个调用首先启动,并且仅当Console.ReadKey
是对控制台的第一次调用,两者都不是答案很清楚。Console.ReadLine()
不会引起同样的问题,这当然很有趣。感谢您抽出时间