Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for multiple processes to complete

I want my program to wait for all processes to finish and then delete some temporary files. I already have a block of code that can do this when dealing with one process at a time, but I can't make it work for multiple processes.

I'll start by showing the code that works. This code correctly runs a process, waits for it to finish, and then deletes the temporary file:

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);            
}  

The above is neatly contained within the foreach loop. What I can't get working is a parallel version of this where the wait statement is outside of the foreach loop:

  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

I think I just need to initialize myWait before going into the foreach loop, but I don't know how to do that. How do I initialize a process without assigning it to anything? Is there some other simple way to do this?

like image 733
Shawn Darichuk Avatar asked Dec 28 '14 21:12

Shawn Darichuk


2 Answers

Not sure if this approach was in any of the linked questions from the comments, but here's one that makes use of List<Task> and 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());
like image 107
Idle_Mind Avatar answered Oct 13 '22 23:10

Idle_Mind


I would store the process handles in a dictionary of script vs process handle, and then later wait for all processes to exit. Below is the code:

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);
}
like image 3
Giri Avatar answered Oct 14 '22 00:10

Giri