Приставка.ReadKey против консоли.С readline с таймером

следующий код является хорошо известным примером, чтобы показать разницу между сборкой отладки и выпуска:

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();
    }
}

если вы запустите это с отладочной конфигурации, таймер будет выводить текущее время каждые две секунды. The GC.Collect не имеет никакого эффекта, потому что компилятор искусственно продлевает жизнь Timer t переменной. В конфигурации release, таймер будет выполняться только один раз. The GC.Collect будет мусор собирать t переменная, и это он.

все это работает так, как должно. Странная вещь, когда вы меняете консоль line.ReadLine для консоли.ReadKey и настройки запуска по таймеру каждые две секунды.

в чем разница между консолью.ReadKey и консоль.С readline? Я понял!--15-->из документации этой консоли.ReadKey блокирует поток, выдающий метод ReadKey. Но GC.Собирайте еще пожары..

почему в жизни Timer t extended, блокируя основной поток?

обновление

при использовании .NET 3.5 это поведение не произойдет!

1 ответов


на 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();
}

причина пульт.Метода WriteLine() ждет, потому что он пытается получить блокировку на Console.InternalSyncObject при создании Console.Out TextWriter впервые.

изменение кода на следующие работы, как и ожидалось, когда мы создаем 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. Подробнее здесь