Console.ReadKey() 与多线程的奇怪行为

2024-05-30

我在使用时遇到一个奇怪的问题Console.ReadKey()在多线程程序中。

我的问题是:为什么会发生这种情况?这是一个错误,还是因为我滥用了Console? (请注意,控制台是supposed为了线程安全,根据文档 http://msdn.microsoft.com/en-us/library/43zwz7ys.aspx.)

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

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.");
        }
    }
}

如果你运行它,你认为会打印出什么don't按一个键?

答案正是你所期望的:

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

现在注释掉Console.WriteLine("X")并再次运行它(无需按键)。 我期望看到这个输出:

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

相反,我看到nothing。然后当我按下一个键时,它会说:

Entering the test() function.

...就是这样。程序退出(当然)并且没有时间进入下一个WriteLine().

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

[EDIT]

如果我添加一个Thread.Sleep(1)就在之前Console.ReadKey()它确实按预期工作。当然,这不应该是必要的,因为Console.ReadKey()无论如何应该永远等待。

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

更多信息:Servy 发现(并且我复制了)该行Console.WriteLine("Entering the test() function.")一直处于阻塞状态,直到按下任意键为止。

构建配置

Visual Studio 2012、Windows 7 x64、四核、英语(英国)。

我已经尝试了.Net4、.Net4.5、x86、AnyCPU 以及调试和发布的所有组合,但它们都无法在我的电脑上工作。但发生了一件非常奇怪的事情。当我第一次尝试 .Net4 的 AnyCPU 版本时它开始工作,但随后又停止工作。看起来很像只影响某些系统的竞争条件。


这是一个竞争条件。这是当第一个 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 调用之后 Main 中没有任何内容
  8. 任务中剩余的代码没有机会运行

当 Console.WriteLine 保留在其中时,其行为不同的原因是对 Console.InitializeStdOutError 的调用没有与 Console.ReadKey 并行发生。

所以简短的回答是:是的,你正在滥用控制台。您可以自己初始化控制台(通过取消引用 Console.Out),或者在启动任务后但在 ReadKey 之前等待事件,然后让任务在第一次调用 Console.WriteLine 后发出事件信号。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Console.ReadKey() 与多线程的奇怪行为 的相关文章

随机推荐

  • 用热图绘制 2 个变量

    我在 python 3 上 有两个变量 x 和 y 其中 x 的范围从 1 到 5 y 的范围从 0 03 到 0 7 然后我有一个方法 它接受 x 和 y 并生成标量数 我想创建一个热图类型图 其中 x 为 x 轴 y 为 y 轴 并使用
  • 在 WebAPI 操作方法中抛出 HttpResponseException 返回空 200 响应

    我正在尝试从我的应用程序返回适当的 Http 代码和响应 但我很挣扎 似乎有两种方法可以返回特定的http响应 我想要处理它的方法是抛出一个HttpResponseException public Information Get int a
  • 如何在 Python 中创建对象的副本?

    我想创建一个对象的副本 我希望新对象拥有旧对象的所有属性 字段的值 但我想要有独立的对象 因此 如果我更改新对象的字段值 旧对象不应受到影响 要获得对象的完全独立的副本 您可以使用copy deepcopy http docs python
  • 使用隧道而不是冒泡的路由命令

    我有一个自定义控件 MyControl 公开自定义命令 我想要家长Window能够调用此命令 以及所有MyControls应该对此做出反应 我已将命令添加到MyControl s CommandBindings集合 它还提供了CanExec
  • 使用 CSS 更改 svg 图像的颜色 [重复]

    这个问题在这里已经有答案了 我的 html 文件中有以下 svg 图像 img class svg src my image link svg 现在 我尝试使用以下 css 代码更改颜色 svg path fill black 然而 一切都
  • Angular,从动态创建的组件中获取ViewChild / ViewContainerRef

    有没有办法从动态创建的组件中获取 ViewContainerRef 我的动态创建的组件内部有一个 ngContent 元素 我想在动态创建后填充该元素 export class Example ViewChild content read
  • 为什么C++标准算法“count”返回difference_type而不是size_t?

    为什么返回类型是std count http en cppreference com w cpp algorithm count the difference type迭代器 通常是ptrdiff t 因为计数永远不可能为负数 不是size
  • 比较两个字符串时如何不包含换行符

    我正在比较两个字符串的更新 我做了一个 string1 string2 结果却有所不同 我把它们放在 添加监视 中 我发现唯一的区别是一个有换行符 另一个没有换行符 string1 This is a test nThis is a tes
  • 将证书安装到 Azure Web 应用上的受信任根证书存储

    如何将证书安装到 Azure Web 应用程序中 以便我的 azure web 应用程序可以通过 SSL 与远程服务通信 此特定证书未由公共 CA 签名 我使用 openssl 生成了一个 ssl 证书 当我将其安装到本地计算机上受信任的根
  • 从字节数组创建 BitmapImage

    我正在创建一个包含任意值的字节数组 并希望将其转换为 BitmapImage bi new BitmapImage using MemoryStream stream new MemoryStream data try bi BeginIn
  • 如何创建 C++ 11 不可默认构造的分配器?

    这个主题出现在关于 Visual Studio 2015 的 std list sort 更改的线程中 std list sort 为什么突然切换到自上而下的策略 https stackoverflow com questions 4062
  • 获取控制器视图上的列表数据

    我有一个视图 其中我在循环中渲染了部分视图 有一个列表 部分视图与列表中的每个项目绑定 输入值后 我没有在控制器上获取列表的值 这是我的观点 table class table width 100 border 0 thead tr sty
  • 从 ASP.NET MVC 将 HTML 表导出到 Excel

    我目前正在使用 ASP NET MVC 并且有一个操作方法 可以在视图中以表格格式显示一些报告 我需要通过单击视图中的按钮将同一个表导出到 Excel 文档 如何才能实现这一目标 您将如何为此创建 Action 方法 在您的控制器操作中 您
  • 更改 Qt 中的语言环境

    我尝试使用 QLocale 和 setDefault 函数更改区域设置 但似乎不起作用 以下是使用 C 本地化库和 QLocale 更改语言环境的示例 对于 C 本地化库 它似乎可以工作 但对于 QLocale setDefault 函数调
  • 为什么要汇集无状态 EJB?

    应用服务器池使用无状态 EJB 的原因是什么 我可以理解 控制传入调用的应用程序工作负载很有用 但这只能证明将作为 FA ADE 与调用者客户端一起提供服务的 EJB 池是合理的 池化内部 EJB 那些未公开且仅在内部调用以执行业务逻辑的
  • 使用“dnupublish”排除发布项目上的文件夹

    如何使用 dnupublish 命令从 wwwroot 中排除文件夹 示例 在我的项目中存在许多文件夹 我需要排除wwwroot lib and wwwroot 源 我正在使用 clr 1 0 0 beta7 12302 The wwwro
  • Flutter Web URL 路由不适用于真实域

    我正在尝试使用一个网址来获取参数并将该参数分配给网络文件内的变量 例如 我的域名是 example com 在这个网站中我需要用户的 ID 我想制作 example com id 123 并获取 123 id 并给出变量 123 值 在 f
  • Storm 中的连接被拒绝错误

    我是 Storm 的新手 我遇到了以下错误 java net ConnectException Connection refused at sun nio ch SocketChannelImpl checkConnect Native M
  • 将 CvSeq 保存到数组

    我对 OpenCV 文档有点迷失 我想将 cvFindContours 返回的 CvSeq 保存到一个数组中 据我了解它将返回 CvContour 的 seq 但我找不到它包含的内容 我应该保存其中的哪些部分 稍后我可以迭代它并说调用 cv
  • Console.ReadKey() 与多线程的奇怪行为

    我在使用时遇到一个奇怪的问题Console ReadKey 在多线程程序中 我的问题是 为什么会发生这种情况 这是一个错误 还是因为我滥用了Console 请注意 控制台是supposed为了线程安全 根据文档 http msdn micr