You can either kick off a background thread or task and wait synchronously in a loop (using WaitForExit), or you can use an asynchronous approach.
Create the Process objects one by one and hook up an event handler to the Exited event that continues with the next Process. Create them with the Process constructor, hook the Exited event handler and then call Start; otherwise, using the static Process.Start, if the process fails between the time Process.Start returns and the event handler is attached, I think the event handler won't get called as it strictly has already exited.
Proof-of-concept: (doesn't handle Dispose, queue access isn't thread-safe, although it should suffice if it truly is serial, and so on)
Queue<Process> ProcessesToRun = new Queue<Process>(new []{ new Process("1"), new Process("2"), new Process("3") });
void ProcessExited(object sender, System.EventArgs e) {
GrabNextProcessAndRun();
}
void GrabNextProcessAndRun() {
if (ProcessesToRun.Count > 0) {
Process process = ProcessesToRun.Dequeue();
process.Exited += ProcessExited;
process.Start();
}
}
void TheEntryPoint() {
GrabNextProcessAndRun();
}