控制台.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时,这种行为不会发生!

控制台.ReadKey vs Console.带定时器的ReadLine

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中的一个变化。更多信息在这里