title: Process.WaitForExit hangs even without using RedirectStandardError/RedirectStandardOutput
body: <p>We have a service which starts a process and waits for process to exit when service is stopped/ user of service calls stop (to stop/kill process started by service).</p>
  
  <p>Sporadically, <code>process.waitForExit(TimeSpan)</code> hangs. </p>
  
  <p>Please note that process started by Service is native process (C++/CLI) process and service is in C#.</p>
  
  <p>Following is the code snippet we are using</p>
  
  <pre><code>public class ApplicationProcessControl : IProcessControl
   {  
      private Process _proc;
      private const int ProcessIdleTimeout = 5000;
  
      public bool Start(string arguments)
      {
          if (IsAlive)
          {
              Log.TraceInfo("Application process already running. Killing it now...");
              _proc.Kill();
          }
  
          var eProcStarted = new Mutex(false, "Mutex111");
  
          _proc = new Process { EnableRaisingEvents = true, StartInfo = new ProcessStartInfo(_exePath, arguments) { RedirectStandardOutput = false,RedirectStandardError = false};
          _proc.Exited += OnProcessExited;
  
          _proc.Start();
          bool started;
          if(_proc == null)
          {
              Log.TraceInfo("Unable to start application process");
              started = false;
          }
          else
          {
              started = eProcStarted.WaitOne(ProcessIdleTimeout);
  
              if(started)
              {
                  Log.TraceInfo($"Application process with id {_proc.Id} started successfully");
              }
          }
          eProcStarted.Dispose();
          return started;
      } 
  
      public void Kill()
      {
          _proc.Kill();
      }
  
      public bool WaitForProcessToExit(TimeSpan timeout)
      {
          return _proc.WaitForExit((int) timeout.TotalMilliseconds);
      }
  
      public event Action ProcessExited;
  
      private void OnProcessExited(object sender, EventArgs e)
      {
          var proc = sender as Process;
  
          if(proc != null)
          {
              proc.Exited -= OnProcessExited;
  
              if(proc.ExitCode == 0)
              {
                  Log.TraceInfo("Application process exited gracefully");
              }
              else
              {
                  Log.DeveloperWarning("Application process exited unexpectedly with code {0}", proc.ExitCode);
                  OnProcessExited();
              }
          }
      }
  
      private void OnProcessExited()
      {
          Action handler = ProcessExited;
          handler?.Invoke();
      }
  }
  
  public interface IProcessControl
  {
      bool IsAlive { get; }
  
      bool Start(string arguments);
  
      bool WaitForProcessToExit(TimeSpan timeout);
  
      void Kill();
  
      event Action ProcessExited;
  }
  
  public class ApplicationClientService: DisposableObject, IComponentService, ITaskControl, IUIControl,
          IDataProvider&lt;AngleFlavors&gt;, IApplicationCloseNotifier
  {
      //...
      private readonly IProcessControl _procCtrl;
  
      public ApplicationClientService(IObjectProvider objPro)
      {
          //...
          _procCtrl.ProcessExited += OnApplicationProcessExited;              
      }
  
      public void Stop()
      {
          //...
          CleanUpAppProcess();
          //...
      }
  
  
      private void CleanUpAppProcess()
      {
          //...
  
          if(!_procCtrl.WaitForProcessToExit(TimeSpan.FromSeconds(5)))
          {
              _procCtrl.Kill();
          }
      }
  
      private void OnApplicationProcessExited()
      {
          if(!_isAppRunning)
          {
              return;
          }
  
          _isAppRunning = false;
          _autoLaunchRequested = false;
          RaiseApplicationClosed();
          Log.DeveloperWarning("Application process closed unexpectedly");
          Log.UserMessageApplicationClosedUnexpectedly();
          ...
      }
  
      protected virtual void RaiseApplicationClosed()
      {
          //AuditApplicationStop();
          //ApplicationClosed?.Invoke();
      }
  
  }
  </code></pre>