多线程Console.ReadKey()的奇怪行为(Strange behaviour of Con

2019-07-20 18:17发布

使用时,我发现了一个奇怪的问题Console.ReadKey()在多线程程序。

我的问题是:为什么会出现这种情况? 它是一个错误,还是因为我滥用Console ? (请注意,控制台应该是线程, 根据文档 。)

这是最简单的代码来解释这一点:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.WriteLine("X");  // Also try with this line commented out.
            Task.Factory.StartNew(test);
            Console.ReadKey();
        }

        private static void test()
        {
            Console.WriteLine("Entering the test() function.");
            Thread.Sleep(1000);
            Console.WriteLine("Exiting the test() function.");
        }
    }
}

你觉得这会打印出来,如果你运行它, 按任何键?

答案就是你所期望的:

X
Entering the test() function.
Exiting the test() function.

现在注释掉Console.WriteLine("X")然后再次运行(不按任何键)。 我期望看到这样的输出:

Entering the test() function.
Exiting the test() function.

相反,我什么也看不见 。 然后当我按一个键,它说:

Entering the test() function.

......仅此而已。 程序退出(当然),它没有时间去下一个WriteLine()

我觉得这种行为很神秘。 这很容易解决,但我很好奇,为什么它会发生。

[编辑]

如果我添加Thread.Sleep(1)之前Console.ReadKey()它的工作如预期。 当然,因为这不应该是必要的Console.ReadKey()应该永远等待呢。

所以它看起来像它可能是某种竞争条件?

更多信息:Servy发现(我有重复),该行Console.WriteLine("Entering the test() function.")直到按下任意键阻止。

构建配置

的Visual Studio 2012,Windows 7的64位,四核,英语(英国)。

我试过.NET4,.Net4.5,X86,AnyCPU和调试的所有组合和释放,他们都不在我的电脑上工作。 但是一个非常奇怪的事情发生了。 它开始工作时,我第一次尝试为.NET4的AnyCPU版本,但随后停止工作了。 看起来非常像只影响一些系统的竞争条件。

Answer 1:

这是一个竞争状态。 这是发生了什么时,第一个Console.WriteLine不存在:

  1. 创建任务,但无法运行
  2. Console.ReadKey执行,呈现Console.InternalSyncObject的锁,和块等待输入
  3. 任务的Console.WriteLine调用Console.Out,要求Console.InitializeStdOutError了第一次初始化设置控制台流
  4. Console.InitializeStdOutError试图锁定Console.InternalSyncObject,但Console.ReadKey已经拥有它,所以它的块
  5. 用户按下一个键,Console.ReadKey回报解除锁定
  6. 到Console.WriteLine电话是畅通,并完成执行
  7. 该进程退出,因为没有什么主要的ReadKey电话后
  8. 在任务中剩余的代码并没有得到机会运行

它的行为不同,当Console.WriteLine命令留在那里是因为调用Console.InitializeStdOutError不与Console.ReadKey并行发生的原因。

所以,简单的答案是:是的,你是滥用控制台。 你既可以初始化安慰自己(提领Console.Out),或者在开始任务后,你会等待一个事件,而是ReadKey前,然后有任务调用Console.WriteLine后的第一时间信号的事件。



Answer 2:

它证实了在.NET 4.5内部错误。 据报道,例如这里: https://connect.microsoft.com/VisualStudio/feedback/details/778650/undocumented-locking-behaviour-in-system-console

这个工作在.NET 3.5和.NET 4。

更多信息: http://blogs.microsoft.co.il/blogs/dorony/archive/2012/09/12/console-readkey-net-4-5-changes-may-deadlock-your-system.aspx

您可以使用简单的解决方法来初始化内部结构,避免堵塞。 只需添加这到beggining(从@renestein):

Console.Error.WriteLine(); 
Console.WriteLine(); 


Answer 3:

这可能发生,因为它是多线程的。 你的主线程正在上并在退出之前你的异步任务有机会向警方报到。 当主线程退出,所有子线程被杀害。

如果你把什么ReadKey之前的等待? 做它输出它是否正确?



文章来源: Strange behaviour of Console.ReadKey() with multithreading