Reputation: 390
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?
Upvotes: 6
Views: 6067
Reputation: 39132
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());
Upvotes: 11
Reputation: 106
Alternative way for future viewers:
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
or using 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
Upvotes: 3
Reputation: 126
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);
}
Upvotes: 3