I'm getting a weird problem when using Console.ReadKey()
in a multithreaded program.
My question is: Why is this happening? Is it a bug, or is it because I am abusing Console
?
(Note that Console is supposed to be threadsafe, according to the documentation.)
It's easiest to explain this with code:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("X"); // Also try with this line commented out.
Task.Factory.StartNew(test);
Console.ReadKey();
}
private static void test()
{
Console.WriteLine("Entering the test() function.");
Thread.Sleep(1000);
Console.WriteLine("Exiting the test() function.");
}
}
}
What do you think that will print out if you run it and don't press a key?
The answer is just what you'd expect:
X
Entering the test() function.
Exiting the test() function.
Now comment out the Console.WriteLine("X")
and run it again (without pressing a key).
I expected to see this output:
Entering the test() function.
Exiting the test() function.
Instead, I see nothing. Then when I press a key, it says:
Entering the test() function.
...and that's it. The program exits (of course) and it doesn't have time to get to the next WriteLine()
.
I find this behaviour very mysterious. It's easy to work around, but I'm intrigued as to why it happens.
[EDIT]
If I add a Thread.Sleep(1)
immediately before Console.ReadKey()
it does work as expected. Of course, this shouldn't be necessary since the Console.ReadKey()
should wait forever anyway.
So it's looking like it might be some kind of race condition?
More info: Servy has found (and I have duplicated) that the line Console.WriteLine("Entering the test() function.")
is blocking until any key is pressed.
Build Configuration
Visual Studio 2012, Windows 7 x64, Quad Core, English (UK).
I've tried all combinations of .Net4, .Net4.5, x86, AnyCPU and debug and release, and none of them work on my PC. But a really weird thing happened. It started working when I first tried the AnyCPU version for .Net4, but then it stopped working again. Seems very much like a race condition that only affects some systems.
This is a race condition. Here is what's happening when the first Console.WriteLine is not there:
The reason it behaves differently when the Console.WriteLine is left in there is because the call to Console.InitializeStdOutError is not happening in parallel with Console.ReadKey.
So the short answer is: yes you are abusing Console. You could either initialize the console yourself (by dereferencing Console.Out), or you would wait on an event after starting the Task, but before ReadKey, and then have the Task signal the event after calling Console.WriteLine the first time.
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