title: Process.Start() hangs when running on a background thread
body: <p>I've been troubleshooting all day. After doing some <a href="http://jake.ginnivan.net/redirecting-process-output" rel="nofollow">research</a> and a lot of trial and error, it seems I've been able to narrow down the issue to the fact that my call to <code>process.Start()</code> doesn't work on a timer thread. The code below works when running on the main thread. Put that exact same code in a timer callback, and it hangs. Why? How do I get it to work with a timer?</p>
  
  <pre><code>private static void RunProcess()
  {
      var process = new Process();
  
      process.StartInfo.FileName = "cmd";
      process.StartInfo.Arguments = "/c exit";
      process.StartInfo.UseShellExecute = false;
      process.StartInfo.RedirectStandardError = true;
      process.StartInfo.RedirectStandardInput = true;
      process.StartInfo.RedirectStandardOutput = true;
  
      process.Start();  // code hangs here, when running on background thread
  
      process.StandardOutput.ReadToEnd();
  
      process.WaitForExit();
  }
  </code></pre>
  
  <p><strong>EDIT</strong></p>
  
  <p>As a test, I used this exact same code on another laptop, and I experienced the same problem. This is complete code that can be pasted into a console app. <code>process.Start()</code> hangs, but as soon as I hit any key to end, <code>process.Start()</code> completes before the program ends.</p>
  
  <pre><code>private static System.Timers.Timer _timer;
  private static readonly object _locker = new object();
  
  static void Main(string[] args)
  {
      ProcessTest();
  
      Console.WriteLine("Press any key to end.");
      Console.ReadKey();
  }
  private static void ProcessTest()
  {
      Initialize();
  }
  private static void Initialize()
  {
      int timerInterval = 2000;
      _timer = new System.Timers.Timer(timerInterval);
      _timer.Elapsed += new ElapsedEventHandler(OnTimerElapsed);
      _timer.Start();
  }
  private static void OnTimerElapsed(object sender, ElapsedEventArgs e)
  {
      if (!Monitor.TryEnter(_locker)) { return; }  // Don't let  multiple threads in here at the same time.
      try
      {
          RunProcess();
      }
      finally
      {
          Monitor.Exit(_locker);
      }
  }
  private static void RunProcess()
  {
      var process = new Process();
      process.StartInfo.FileName = "cmd";
      process.StartInfo.Arguments = "/c exit";
      process.StartInfo.UseShellExecute = false;
      process.StartInfo.RedirectStandardError = true;
      process.StartInfo.RedirectStandardInput = true;
      process.StartInfo.RedirectStandardOutput = true;
      process.Start();  // ** HANGS HERE **
      process.StandardOutput.ReadToEnd();
      process.WaitForExit();
  }
  </code></pre>