c# – 具有多线程的Console.ReadKey()的奇怪行为

c# – 具有多线程的Console.ReadKey()的奇怪行为,第1张

概述在多线程程序中使用Console.ReadKey()时,我会遇到一个奇怪的问题. 我的问题是:为什么会发生这种情况?这是一个bug,还是因为我滥用控制台? (注意,控制台应该是线程安全的,according to the documentation.) 用代码解释最简单: using System;using System.Threading;using System.Threading.Ta 在多线程程序中使用Console.ReadKey()时,我会遇到一个奇怪的问题.

我的问题是:为什么会发生这种情况?这是一个BUG,还是因为我滥用控制台?
(注意,控制台应该是线程安全的,according to the documentation.)

用代码解释最简单:

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

你认为如果运行它会打印出来,而不是按键?

答案就是你所期望的:

XEntering the test() function.Exiting the test() function.

现在注释掉Console.Writeline(“X”)并再次运行(不用按键).
我预计会看到这个输出:

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

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

Entering the test() function.

…就是这样程序退出(当然),它没有时间到达下一个Writeline().

我觉得这个行为很神秘.很容易解决,但我很感兴趣为什么会这样.

[编辑]

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

所以看起来可能是某种种族条件?

更多信息:Servy发现(和我已经重复),Console.Writeline(“输入test()函数”)的行被阻塞,直到按下任何键.

构建配置

Visual Studio 2012,windows 7 x64,Quad Core,英语(英国).

我已经尝试过所有的.Net4,.Net4.5,x86,Anycpu的组合,并且调试和释放,并且它们都不在我的电脑上工作.但是真的很奇怪的事情发生了.当我第一次尝试使用.Net4的Anycpu版本时,它开始工作,但是它再次停止工作.似乎非常喜欢竞争条件,只影响一些系统.

解决方法 这是一个种族条件.当第一个Console.Writeline不在那里时,会发生什么:

>任务创建,但不运行
> Console.ReadKey执行,对Console.InternalSyncObject执行锁定,并阻止等待输入
> Task的Console.Writeline调用Console.Out,调用Console.InitializeStdOutError进行首次初始化以设置控制台流
> Console.InitializeStdOutError尝试锁定Console.InternalSyncObject,但Console.ReadKey已经拥有它,所以它阻止
>用户按下一个键和Console.ReadKey返回,释放锁定
>对Console.Writeline的调用被解除阻塞并完成执行
>进程退出,因为ReadKey调用后Main中没有任何内容
>任务中剩下的代码没有机会运行

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

所以简短的答案是:是的,你正在滥用控制台.您可以自己初始化控制台(通过取消引用Console.Out),或者在启动任务后,等待ReadKey之前的事件,然后在第一次调用Console.Writeline后将Task发送给事件.

总结

以上是内存溢出为你收集整理的c# – 具有多线程的Console.ReadKey()的奇怪行为全部内容,希望文章能够帮你解决c# – 具有多线程的Console.ReadKey()的奇怪行为所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1263269.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存