等待多个进程完成

6
我希望我的程序可以等待所有的进程结束后再删除一些临时文件。我已经有了一段代码可以在处理一个进程时完成这个任务,但是无法处理多个进程。
下面先展示可以运行一个进程、等待其结束并删除临时文件的代码:
foreach (string script in scriptList)
{
     ProcessStartInfo myProcess = new ProcessStartInfo();
     myProcess.FileName = accoreconsolePath;
     myProcess.Arguments = "/s \"" + script + "\"";
     myProcess.CreateNoWindow = true;         
     Process myWait = Process.Start(myProcess);
     myWait.WaitForExit();

     File.Delete(script);            
}  

以上内容都包含在foreach循环中。我无法让一个并行的版本按照预期工作,其中等待语句在foreach循环之外:
  Process myWait;
  foreach (string script in scriptList)
  {
     ProcessStartInfo myProcess = new ProcessStartInfo();
     myProcess.FileName = accoreconsolePath;
     myProcess.Arguments = "/s \"" + script + "\"";
     myProcess.CreateNoWindow = true;
     myWait = Process.Start(myProcess);
  }
  myWait.WaitForExit();                             //error: use of unassigned local variable "myWait"
  //delete file would go here

我认为我只需要在进入foreach循环之前初始化myWait,但我不知道如何做。如何初始化一个进程而不将其分配给任何东西?还有其他简单的方法吗?


1
List<Process> myWait = new List<Process>(); - Hans Passant
1
请看这个非常相似的问题:https://dev59.com/Wn_aa4cB1Zd3GeqP8NLF#23741387 - Jan Köhler
1
可能是重复的问题:如何等待多个命令行操作完成? - shf301
3个回答

10

我不确定这种方法是否出现在评论中提供的任何链接中,但下面这种方法使用了 List<Task>Task.WaitAll()

List<Task> tasks = new List<Task>();            
foreach (string script in scriptList)
{
    string tmpScript = script;
    tasks.Add(Task.Run(delegate {
        ProcessStartInfo myProcess = new ProcessStartInfo();
        myProcess.FileName = accoreconsolePath;
        myProcess.Arguments = "/s \"" + tmpScript + "\"";
        myProcess.CreateNoWindow = true;
        Process.Start(myProcess).WaitForExit();
        File.Delete(tmpScript);
    }));
}
Task.WaitAll(tasks.ToArray());

WaitForExitAsync() 可在 CLR 5+ 中使用,但如果您没有可用的版本,则将 WaitForExit() 包装在匿名委托中比升级运行时更小。谢谢! - Eliot Gillum

3

未来观众的另一种选择:

var NoOfCores = 4;
Parallel.For(0, scriptList.Count,new ParallelOptions {MaxDegreeOfParallelism=NoOfCores }, index =>
{   
    Process proc= new Process();
    proc.StartInfo.FileName = "filename";
    proc.StartInfo.WorkingDirectory = "optional";
    proc.StartInfo.Arguments = scriptList[index];   
    proc.Start();
    proc.WaitForExit();
    //code here will be executed after finishing each thread
}
//code here will be executed after finishing all the threads

或者使用 Parallel.ForEach

var NoOfCores = 4;
Parallel.For(0, scriptList,new ParallelOptions {MaxDegreeOfParallelism=NoOfCores }, script=>
{   
    Process proc= new Process();
    proc.StartInfo.FileName = "filename";
    proc.StartInfo.WorkingDirectory = "optional";
    proc.StartInfo.Arguments = script;   
    proc.Start();
    proc.WaitForExit();
    //code here will be executed after finishing each thread
}
//code here will be executed after finishing all the threads

3
我会把进程句柄存储在脚本和进程句柄之间的字典中,并稍后等待所有进程退出。以下是代码:

我会把进程句柄存储在脚本和进程句柄之间的字典中,并稍后等待所有进程退出。以下是代码:

var processes = new Dictionary<string,Process>();

foreach (string script in scriptList)
{
    ProcessStartInfo myProcess = new ProcessStartInfo();
     myProcess.FileName = accoreconsolePath;
     myProcess.Arguments = "/s \"" + script + "\"";
     myProcess.CreateNoWindow = true;
     myWait = Process.Start(myProcess);
     processes.Add(script, myWait);
}

foreach(var script in processes.Keys)
{
    Process process = processes[script];

    process.WaitForExit();
    process.Close();

    File.Delete(script);
}

Dictionary<TKey, TValue> 上迭代 TKey 并将第一行作为 TValue 的赋值与在字典上迭代 Pair<TKey, TValue> 并使用 KeyValue 属性相同,除了避免使用哈希算法。 - Mephy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接