Strange behaviour of Console.ReadKey() with multithreading Strange behaviour of Console.ReadKey() with multithreading multithreading multithreading

Strange behaviour of Console.ReadKey() with multithreading


This is a race condition. Here is what's happening when the first Console.WriteLine is not there:

  1. Task is created, but not run
  2. Console.ReadKey executes, takes a lock on Console.InternalSyncObject, and blocks waiting for input
  3. The Task's Console.WriteLine calls Console.Out, which calls Console.InitializeStdOutError for first-time initialization to set up the console streams
  4. Console.InitializeStdOutError attempts to lock on Console.InternalSyncObject, but Console.ReadKey already has it, so it blocks
  5. The user presses a key and Console.ReadKey returns, releasing the lock
  6. The call to Console.WriteLine is unblocked and finishes executing
  7. The process exits, because there is nothing in Main after the ReadKey call
  8. The remaining code in the Task does not get a chance to run

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.


It is confirmed internal bug in .NET 4.5.It has been reported for example here: https://connect.microsoft.com/VisualStudio/feedback/details/778650/undocumented-locking-behaviour-in-system-console

This worked in .NET 3.5 and .NET 4.

More info: http://blogs.microsoft.co.il/blogs/dorony/archive/2012/09/12/console-readkey-net-4-5-changes-may-deadlock-your-system.aspx

You can use simple workaround to init internal structures and avoid blocking. Just add this to the beggining (from @renestein):

Console.Error.WriteLine(); Console.WriteLine(); 


This is probably occurring BECAUSE it is multi-threaded. Your main thread is moving on and exiting before your async task has a chance to report back. When the main thread exits, all child threads are killed.

What if you place a waiting before the ReadKey? does it output it correctly?