使用Task.Run()写入控制台失败

时间:2013-01-17 16:52:22

标签: c# .net-4.5

我的一位同事在我们的代码中发现了一个问题,并且花了一段时间来确切地查找正在发生的事情,但最好通过这个简单的例子来证明:

// 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();
    }
}

从中解决这个问题很清楚,从主线程到任何地方写入控制台都会允许后台线程写入控制台,但是我们很难理解为什么会发生这种情况。任何人都可以解释从主线程写入控制台的内容是什么,第一个片段没有?

2 个答案:

答案 0 :(得分:5)

实际上,第一种情况并没有失败。应用程序结束前出现“Hello World”。这是一个经典的Race Condition。在第一种情况下,来自主线程的Console.ReadKey()击败任务,而在第二种情况下,任务获胜。不幸的是,我无法告诉你为什么写空字符串会让任务获胜。

答案 1 :(得分:5)

我怀疑发生了什么事。我观察到的是:

  • 如果您在启动ReadKey之前使用控制台的输出执行任何,那就没关系。这包括提取Console.Out但不使用
  • 如果您在Console.WriteLine来电之前设置了Console.ReadKey来电> ,那么就可以了(并且您可以进行多次WriteLine次来电< em> while ReadKey正在等待

我怀疑使用控制台的第一个操作获取初始化锁定(以避免它被初始化两次)并且ReadKey方法保持锁定直到一个键已被阅读。这肯定会解释我到目前为止所运行的所有程序。

执行假设初始化的操作很有趣 - 阅读Console.Out“修复了”问题,但是从Console.In读取却没有。

我怀疑ReadKey初始化输出,因为该值仍然会回显到控制台......但我不想发誓。

有趣的是,使用Console.ReadLine()代替Console.ReadKey()并不会导致问题。