【问题标题】:Wait until multiple command line processes complete?等到多个命令行进程完成?
【发布时间】:2014-05-19 15:08:29
【问题描述】:

我需要执行许多命令行脚本。它们当前存储在List 中。我想同时运行它们,并在所有这些都完成后继续下一步。

我尝试了下面显示的方法,但发现它缺少,因为最后一个命令不一定 end 最后。事实上,我发现最后一个命令甚至可以是 first 完成的。所以,我相信我需要像 WaitForExit() 这样的东西,但直到 所有 执行进程完成后才会返回。

for (int i = 0; i < commands.Count; i++)
{
    string strCmdText = commands[i];
    var process = System.Diagnostics.Process.Start("CMD.exe", strCmdText);
    if (i == (commands.Count - 1))
    {
        process.WaitForExit();
    }
}
//next course of action once all the above is done

【问题讨论】:

    标签: c# command-line process wait


    【解决方案1】:

    由于每次调用 Process.Start 都会启动一个新进程,因此您可以单独跟踪它们,如下所示:

    var processes = new List<Process>();
    for (int i = 0; i < commands.Count; i++)
    {
        string strCmdText = commands[i];
        processes.Add(System.Diagnostics.Process.Start("CMD.exe", strCmdText));
    }
    
    foreach(var process in processes)
    {
        process.WaitForExit();
        process.Close();
    }
    

    编辑

    Process.Close() 在 cmets 中添加

    【讨论】:

    • 我发现这个解决方案比任何提供的任务并行方法都要好,因为它不会不必要地使用/创建更多线程
    • 可能不是绝对必要的,因为Process 继承自Component 的终结器,但最好尽早处理。在这个例子中也很容易做到(只需在每次循环迭代中 WaitForExit() 之后调用 Close())。
    • @Edin 完全正确。我看不出有任何理由假装您的程序正在执行并行化,而实际上它只是同时运行的外部进程
    【解决方案2】:

    使用一个 Task 数组并等待它们全部完成。

    var tasks = new Task[commands.Count];
    for (int i = 0; i < commands.Count; i++)
    {
        tasks[i] = Task.Factory.StartNew(() => {
           string strCmdText = commands[i];
           var process = System.Diagnostics.Process.Start("CMD.exe", strCmdText);
           process.WaitForExit();
        });
    }
    
    Task.WaitAll(tasks);
    

    或者,更类似于 LINQ:

    var tasks = commands.Select(strCmdText => Task.Factory.StartNew(() => {
        var process = System.Diagnostics.Process.Start("CMD.exe", strCmdText);
        process.WaitForExit();
    })).ToArray();
    Task.WaitAll(tasks);
    

    【讨论】:

      【解决方案3】:

      至少在 Windows 上,您可以使用 WaitHandle.WaitAll()

      using System;
      using System.Diagnostics;
      using System.Threading;
      using Microsoft.Win32.SafeHandles;
      using static System.FormattableString;
      
      public class ProcessWaitHandle : WaitHandle
      {
          public ProcessWaitHandle(Process process) =>
              this.SafeWaitHandle = new SafeWaitHandle(process.Handle, false);
      }
      
      class Program
      {
          static void Main(string[] args)
          {
              int processesCount = 42;
              var processes = new Process[processesCount];
              var waitHandles = new WaitHandle[processesCount];
              try
              {
                  for (int i = 0; processesCount > i; ++i)
                  {
                      // exit immediately with return code i
                      Process process = Process.Start(
                          "cmd.exe",
                          Invariant($"/C \"exit {i}\""));
      
                      processes[i] = process;
                      waitHandles[i] = new ProcessWaitHandle(process);
                  }
      
                  WaitHandle.WaitAll(waitHandles);
                  foreach (Process p in processes)
                  {
                      Console.Error.WriteLine(
                          Invariant($"process with Id {p.Id} exited with code {p.ExitCode}"));
                  }
              }
              finally
              {
                  foreach (Process p in processes)
                  {
                      p?.Dispose();
                  }
      
                  foreach (WaitHandle h in waitHandles)
                  {
                      h?.Dispose();
                  }
              }
      
              Console.WriteLine("Press any key to continue...");
              Console.ReadKey(false);
          }
      }
      

      这种方法还提供了使用其他 WaitAll 重载的可能性,例如超时等待。

      【讨论】:

        猜你喜欢
        • 2015-06-13
        • 1970-01-01
        • 2015-02-25
        • 2013-01-19
        • 2013-09-01
        • 1970-01-01
        • 2011-02-19
        • 2016-01-07
        • 1970-01-01
        相关资源
        最近更新 更多