title: Using C# Process Class for Multiple Concurrent Instances of same .EXE Using SQL Server Slow
body: <p>I have a standalone .EXE file written in Micro Focus .NET COBOL. It uses an ODBC DSN to access a SQL Server database to insert records into various tables.</p>
  <p>I have a C# application that instantiates multiple process classes with startInfo objects to set up params for the COBOL .EXE file and starts the processes concurrently. I wrote this over 12 years ago and it ran fine on a Windows Server.</p>
  <p>However, I'm trying to run it on a very powerful Windows 11 PC with SQL Server 2016 Standard edition. If I run 4 instances concurrently - all 4 start quickly and start processing but the first instance appears to be getting about 90% of the resource attention. The other three run slowly. When the first finishes, the second picks up some steam, but the other two get even slower. Take a significant amount of time for the 4th process to finally end.</p>
  <p>In looking at the resource monitor, I have 24 CPUs showing but only CPU 2 has SQL Server and the 4 processes assigned although sometimes CPU 3 shows one of the processes. All of the other CPU's, memory and disk are running low utilization.</p>
  <p>I tried setting thread affinity to spread across CPU's but no effect. Any ideas? Here's the relevant code:</p>
  <pre><code>   processes = new object[processCount];
         ....
     for (int i = 0; i &lt; processCount; i++)
            {
                  // Set up startinfo (starting parms for each process)
                  Process aProcess = new Process();
                  ProcessStartInfo startInfo = new ProcessStartInfo();
                  // create common startinfo parms for all processes
                  startInfo.CreateNoWindow = false;
                  startInfo.FileName = tbCOBOLExe.Text;
                  startInfo.WorkingDirectory = fe.Directory.FullName;
                  startInfo.UseShellExecute = false;
                  startInfo.RedirectStandardOutput = true;
                    ....
                  aProcess.StartInfo = startInfo;
                  processes[i] = aProcess; 
           }
  
               // Start Processes Asynchronously
              for (int k = 0; k &lt; processes.Length; k++)
              {
                  Process theProcess = (Process) processes[k];
                  theProcess.Start();
                  // spread the processes across CPUs. Assume at least 8 CPUs
                  if (k &lt; 7)
                  {
                      theProcess.ProcessorAffinity = (IntPtr)(k + 1);
                  }
                  Thread.Sleep(1000);
              }
  
                  // gather console output
              StreamWriter outConsole = new StreamWriter(fe.Directory.FullName + &quot;\\SYSOUT&quot; + outfilePrefix + &quot;.txt&quot;);
              outConsole.WriteLine(&quot;******* The Job started at: &quot; + DateTime.Now.ToLocalTime());
              while (pCompleted &lt; processes.Length)
              {
                  // sleep for 3 seconds while processes are running
                  // Thread.Sleep(3000);
                  for (int l = 0; l &lt; processes.Length; l++)
                  {
                      Process theProcessStarted = (Process)processes[l];
                      try
                      {
                          if (theProcessStarted.HasExited)
                          {
                              pCompleted++;
                              outConsole.WriteLine(theProcessStarted.StandardOutput.ReadToEnd());
                              outConsole.WriteLine(&quot;Process Completed at: &quot; + DateTime.Now.ToLocalTime());
                              theProcessStarted.Close();
                          }
                      }
                      catch (Exception ep)
                      {
                      // we get an exception above when referencing a closed process- ignore
                      }
                  }
              }
  </code></pre>