The following code is a well known example to show the difference between a debug and release build:
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();
}
}
If you run this with a debug configuration, the timer will output the current time every two seconds. The GC.Collect
doesn't have any effect because the compiler artificially extends the life of the Timer t
variable. In a release configuration, the timer will execute only once. The GC.Collect
will garbage collect the t
variable and that's it.
This all works like it should. The strange thing is, when you change the line Console.ReadLine to Console.ReadKey both configurations run the timer every two seconds.
What is the difference between Console.ReadKey and Console.ReadLine? I understood from the documentation that Console.ReadKey blocks the thread issuing the ReadKey method. But the GC.Collect still fires..
Why is the lifetime of Timer t
extended by blocking the main thread?
When using .NET 3.5, this behavior won't occur!
Difference between ReadLine(), Read(), ReadKey() in C# As MSDN is actually pretty clear. Reads the next line of characters from the standard input stream. simply you can say, it read all the characters from user input. (and finish when press enter).
ReadKey() Method makes the program wait for a key press and it prevents the screen until a key is pressed. In short, it obtains the next character or any key pressed by the user. The pressed key is displayed in the console window(if any input process will happen).
One of the most common uses of the ReadKey() method is to halt program execution until the user presses a key and the app either terminates or displays an additional window of information. The following example uses the ReadKey() method to wait for the user to press the Enter key before terminating the app.
The C# readline method is mainly used to read the complete string until the user presses the Enter key or a newline character is found. Using this method, each line from the standard data input stream can be read. It is also used to pause the console so that the user can take a look at the output.
The Console.ReadKey()
method locks the Console.InternalSyncObject
whereas the Console.ReadLine()
method does not. When the TimerCallBack()
method tries to write to the Console
the Thread
waits because the Console.InternalSyncObject
is still locked. Therefore GC.Collect()
is never called. As soon as you hit a key the lock is released and GC.Collect()
is called.
I changed your code to the following which doesn't lock the Console.InternalSyncObject
and it only beeps once in Release and every 2 seconds in Debug.
private static void TimerCallback(Object o)
{
Console.Beep();
GC.Collect();
}
The reason the Console.WriteLine() waits is because it tries to acquire a lock on the Console.InternalSyncObject
when creating the Console.Out
TextWriter
for the first time.
Changing your code to the following works as expected as we create the Console.Out
TextWriter
before starting the timer.
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();
}
This is due to a change in .NET 4.5. More info here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With