控制台.ReadKey vs Console.带定时器的ReadLine
本文关键字:定时器 ReadLine Console ReadKey vs 控制台 | 更新日期: 2023-09-27 18:06:30
下面的代码是一个众所周知的例子,用来显示调试版本和发布版本之间的区别:
using System;
using System.Threading;
public static class Program
{
public static void Main()
{
Timer t = new Timer(TimerCallback, null, 0, 2000);
Console.ReadLine();
}
private static void TimerCallback(Object o)
{
Console.WriteLine("In TimerCallback: " + DateTime.Now);
GC.Collect();
}
}
如果在调试配置下运行此命令,计时器将每两秒输出一次当前时间。GC.Collect
没有任何影响,因为编译器人为地延长了Timer t
变量的寿命。在发布配置中,计时器将只执行一次。GC.Collect
将垃圾收集t
变量,就是这样。
这一切都像它应该工作。奇怪的是,当您更改Console行时。ReadLine到控制台。ReadKey 两个配置每两秒运行一次定时器。
控制台和控制台的区别是什么?ReadKey和Console.ReadLine?我从文档中了解到Console。ReadKey阻塞了发出ReadKey方法的线程。但是GC。收集静止的火…
为什么Timer t
的生命周期通过阻塞主线程来延长?
当使用。net 3.5时,这种行为不会发生!
Console.ReadKey()
方法锁定Console.InternalSyncObject
,而Console.ReadLine()
方法不锁定。当TimerCallBack()
方法试图写入Console
时,Thread
等待,因为Console.InternalSyncObject
仍然处于锁定状态。因此,GC.Collect()
永远不会被调用。只要你按下一个键,锁就会被释放,GC.Collect()
就会被调用。
我将你的代码更改为以下不锁定Console.InternalSyncObject
,它只在发布中发出一次蜂鸣声,在调试中每2秒发出一次。
private static void TimerCallback(Object o)
{
Console.Beep();
GC.Collect();
}
Console.WriteLine()等待的原因是因为它在第一次创建Console.Out
TextWriter
时试图获取Console.InternalSyncObject
上的锁。
将您的代码更改为以下工作,因为我们在启动计时器之前创建了Console.Out
TextWriter
。
public static void Main()
{
Console.WriteLine("Loaded");
Timer t = new Timer(TimerCallback, null, 0, 2000);
Console.ReadKey();
}
private static void TimerCallback(Object o)
{
Console.WriteLine("In TimerCallback: " + DateTime.Now);
GC.Collect();
}
这是由于。net 4.5中的一个变化。更多信息在这里