Strange Behaviour of Console.Readkey() with 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.

Sometimes thread does not start

This is an ideal case of race condition. Here you are creating a thread and subsequently starting it. But keep in mind, there is a delay for the thread to actually run once you call start method on it. Possibly, this delay give chance for your Console.ReadKey method to get into flow of execution and wait for user input. At this stage, Console.ReadKey method block your console through taking a lock on Console.InternalSyncObject, and blocks waiting for input. This case other execution path to block until we key in. Once you press the Key, which indirectly release the lock on Console.InternalSyncObject and allow the thread continue its execution. I presume, this is what happening in your case.

Though it is not to replace what you are trying to achieve, you can see the thread executing when you replace Console.RedKey to Console.ReadLine().

multithreading behavior strange C#!

See Eric Lippert's excellent blog post on this issue.

This is being caused by access to a "modified closure".

Change your loop's body to this:

for (int i = 1; i<=3; i++)
{
int j = i; // Prevent use of modified closure.
Thread thread = new Thread(() => testThread("" + j + "__"));

thread.Start();
}

(Note that for a foreach loop, this was fixed in .Net 4.5, but it was NOT fixed for a for loop.)



Related Topics



Leave a reply



Submit