title: Process.WaitForExit() Much Slower After Refactor When Calling Taskkill
body: <p>I am in the process of rewriting an application I made some time ago. One of the functions available to users is to enumerate all processes which are currently running over the active Citrix session and display them (Similar Windows Task Manager). The issue is when querying <code>tasklist</code> on the user's machine, and the length of time taken to output the results of this command. </p>
  
  <p>My new version of the code takes a much more Object-Oriented approach by using non-static classes to represent <code>Sessions</code> and <code>Procs</code> (Processes).</p>
  
  <p>The original code looked like this, and it worked fairly well in terms of length of time taken to actually run the query and retrieve the output results:</p>
  
  <p><strong>OLD CODE:</strong></p>
  
  <pre><code>    public static Dictionary&lt;string, string&gt; GetProcs(string server, string sessID)
      {
          SecureString ss = CreatePW();
          ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/C tasklist /S " + server + " /FI \"SESSION eq " + sessID + "\" /FO CSV /NH")
          {
              WindowStyle = ProcessWindowStyle.Hidden,
              UseShellExecute = false,
              RedirectStandardOutput = true,
              RedirectStandardError = true,
              CreateNoWindow = true,
  
              WorkingDirectory = @"C:\windows\system32",
              Verb = "runas",
              Domain = "BARDOM1",
              UserName = "zzkillcitrix",
              Password = ss
          };
  
          List&lt;string&gt; procList = new List&lt;string&gt;();
          Process proc = Process.Start(startInfo);
          proc.OutputDataReceived += (x, y) =&gt; procList.Add(y.Data);
          proc.BeginOutputReadLine();
          proc.WaitForExit();
  
          // Create a new ditionary ...
          Dictionary&lt;string, string&gt; procDict = new Dictionary&lt;string, string&gt;();
  
          for (int i = 0; i &lt; procList.Count - 1; i++)
          {
              if (procDict.ContainsKey(procList[i].Split(',')[0].Trim('"')))
              {
                  // Do nothing 
              }
  
              else
              {
                  procDict.Add(procList[i].Split(',')[0].Trim('"'), procList[i].Split(',')[1].Trim('"'));
  
              }
          }
  
          return procDict;
      }
  </code></pre>
  
  <p>This entire application as very messy and so I've rewritten most of it, but my only concern is that the new method for retrieving the current list of processes is a lot slower (probably around 4 - 5 times slower than the old version). </p>
  
  <hr>
  
  <p><strong>NEW CODE:</strong></p>
  
  <p><strong>In the ProcessHelper class</strong></p>
  
  <pre><code>    public static List&lt;Proc&gt; GetProcList(Session session)
      {
          // Get the current tasks
          List&lt;string&gt; processQueryResult = TaskList(session);
          List&lt;Proc&gt; procList = new List&lt;Proc&gt;();
  
          foreach (var processDetails in processQueryResult)
          {
              // Only create the Proc if the process is in the 'valid' array ...
              // Get the procname
              string procName = processDetails.Split(',')[0].Trim('"').ToUpper();
  
              // Make sure it's position is not -1 ...
              int pos = Array.IndexOf(MyGlobals.ProcArray, procName);
              if (pos &gt; -1)
              {
                  int procId = Int32.Parse(processDetails.Split(',')[1].Trim('"'));
  
                  Proc p = new Proc(procName, procId, session.ServerName, session.ID);
                  procList.Add(p);
  
                  SupportMI.Trace = "--adding" + p.Name + "--";
              }
          }
  
          return procList;
      }
  
      private static List&lt;string&gt; TaskList(Session session)
      {
          string cmdIn = "tasklist /S " + session.ServerName + " /FI \"SESSION eq " + session.ID + "\" /FO CSV /NH";
          List&lt;string&gt; cmdOut = Cmd.StdOutAdminList(cmdIn);
  
          return cmdOut;
      }
  </code></pre>
  
  <p><strong>In the Cmd class</strong></p>
  
  <pre><code>    public static List&lt;string&gt; StdOutAdminList(string args)
      {
          List&lt;string&gt; cmdOut = new List&lt;string&gt;();
  
          SecureString ss = pw();
          ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/C " + args)
          {
              WindowStyle = ProcessWindowStyle.Hidden,
              UseShellExecute = false,
              RedirectStandardOutput = true,
              RedirectStandardError = true,
              CreateNoWindow = true,
  
              WorkingDirectory = @"C:\windows\system32",
              Verb = "runas",
              Domain = "BARDOM1",
              UserName = "zzkillcitrix",
              Password = ss
          };
  
          cmdOut = ExecuteListCommand(startInfo);
          return cmdOut;
      }
  
      private static List&lt;string&gt; ExecuteListCommand(ProcessStartInfo startInfo)
      {
          List&lt;string&gt; procList = new List&lt;string&gt;();
  
          Process p = Process.Start(startInfo);
          p.OutputDataReceived += (x, y) =&gt; procList.Add(y.Data);
          p.BeginOutputReadLine();
          p.WaitForExit();
  
          return procList;
      }
  </code></pre>
  
  <p><strong>Possible Reasons</strong></p>
  
  <p>In the new version of the Program I also introduced several new objects (For example a Session class and a Proc class to store information about separate processes). Is it possible that adding these extra classes slows down the Process.WaitForExit() method?</p>
  
  <p>After some debugging, it seems that the point at which the program is slowing down relative to the old code is when <code>Process.WaitForExit()</code> is called - Does anything affect this method call apart from the ProcessStartInfo details? if not, then I am very confused as I set the ProcessStarInfos to the same settings but still the new code has a delay. </p>
  
  <p>Another thought I had was that perhaps the addition of more objects, meaning more parameters being passed around, is slowing down the whole application, which is somehow manifesting itself in the way described above.</p>
  
  <p>Any insight into why this may be happening is much appreciated. Please let me know if I can provide any more details or code, or run any tests.</p>
  
  <p>I also considered calling "tasklist" directly from <code>Process</code> rather than "cmd", but this had no affect, so I have ruled this out as a possibility.</p>