4

I faced with some problem I cannot understand why it is happening. Here is simple example:

class ConsoleApp
{
  static void Main(string[] args)
  {
    Thread workThread = new Thread(ThreadProc);
    //Console.WriteLine("Starting"); // uncomment this
    workThread.Start();
    Console.ReadKey(true); // first ReadKey
    Console.ReadKey(true); // second ReadKey
  }

  static void ThreadProc()
  {
    Console.WriteLine("ThreadProc started");
    Random rnd = new Random();
    for (int i = 0; i < 5; i++)
    {
      int timeout = rnd.Next(500, 1000);
      Thread.Sleep(timeout);
      Console.WriteLine("ThreadProc {0} slept {1} ms", i, timeout);
    }
  }
}

When I run this, workThread doesn't start until I press some key (after first ReadKey). If I uncomment first Console.WriteLine, workThread starts immediately.

Can anyone explain this behavior?

Alexander Kuzin
  • 463
  • 4
  • 13
  • 9
    A race condition. See http://stackoverflow.com/questions/15143931/strange-behaviour-of-console-readkey-with-multithreading – Maarten May 07 '13 at 07:30
  • I copied your code and tried this, but the thread immediately starts, regardless of commenting or uncommenting that line. – John Willemse May 07 '13 at 07:31
  • I can't repeat this. What environment is this running under? – Nick May 07 '13 at 07:33
  • Alexander, Try with replacing `Console.ReadKey` with `System.Windows.Forms.Application.Run(new Form());` – I4V May 07 '13 at 07:34
  • 1
    Thanks, the answer in http://stackoverflow.com/questions/15143931/strange-behaviour-of-console-readkey-with-multithreading explained everything. I tried to use Debug.WriteLine() and saw that thread is actually started, but Console.WriteLine locked execution. – Alexander Kuzin May 07 '13 at 08:37

2 Answers2

4

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().

S.N
  • 4,910
  • 5
  • 31
  • 51
  • 2
    The thread starts immediately. It is `Console.WriteLine` that waits for the console lock to be released before it finishes executing.. – Vincent McNabb May 07 '13 at 07:49
0

Static class Console is thread-safe, there's a lock inside. Sometimes ReadKey call takes the lock before calls inside your ThreadProc. It is called "race condition"

astef
  • 8,575
  • 4
  • 56
  • 95