繁体   English   中英

Console.ReadKey与带有Timer的Console.ReadLine

[英]Console.ReadKey vs Console.ReadLine with a Timer

以下代码是一个众所周知的示例,用于显示调试版本和发布版本之间的区别:

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行更改为Console.ReadKey时, 两个配置每两秒运行一次计时器。

Console.ReadKey和Console.ReadLine有什么区别? 从文档中了解到Console.ReadKey阻塞了发出ReadKey方法的线程。 但是GC.Collect仍然会发射..

为什么通过阻塞主线程来延长Timer t的生命周期?

更新

使用.NET 3.5时,不会发生此行为!

Console.ReadKey()方法锁定Console.InternalSyncObjectConsole.ReadLine()方法则不锁定。 TimerCallBack()方法尝试写入ConsoleThread等待,因为Console.InternalSyncObject仍然被锁定。 因此从不调用GC.Collect() 只要按下某个键,就会释放锁定并GC.Collect()

我将您的代码更改为以下内容,该代码不会锁定Console.InternalSyncObject ,它只在Release中发出一次哔声,在Debug中每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的变化。 更多信息在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM