I am creating a GUI application using Visual C# 2005 (net framework 2). I use the following code to start a process:
Process process = new Process();
process.StartInfo = new ProcessStartInfo("app.exe");
process.StartInfo.WorkingDirectory = "";
process.StartInfo.Arguments = "some arguments";
process.Start();
process.WaitForExit();
I want my application to wait until this process is finished, so I used WaitForExit. But the GUI Windows freezes while app.exe is running. I want it to respond (e.g. press a cancel button), but I don't want the code to continue, because there is another process to start after than. Thanks in advance!
You can capture the Exited event of the Process class:
void someMethod()
{
//...possibly more code here
Process process = new Process();
process.StartInfo = new ProcessStartInfo("app.exe");
process.StartInfo.WorkingDirectory = "";
process.StartInfo.Arguments = "some arguments";
process.Exited += new EventHandler(ProcessExited);
process.Start();
}
void ProcessExited(object sender, System.EventArgs e)
{
//Handle process exit here
}
Your waiting for the process on the only thread of your application that is also responsible for handling all GUI events. If you want to wait for some event (like some other process to finish) and still have your code notified of the event then you have to wait on another thread or use an event handler.
This should help. Basically for windows forms and simple tasks like this, a BackgroundWorker is handy. Below is some simple code to launch notepad and wait for it to either close or the user can kill it by clicking cancel.
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerSupportsCancellation = true;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Process process = new Process();
process.StartInfo = new ProcessStartInfo("notepad.exe");
process.Start();
while (!process.HasExited)
{
if (backgroundWorker1.CancellationPending)
{
process.Kill();
continue;
}
else
Thread.Sleep(1000);
}
}
private void Start_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void Cancel_Click(object sender, EventArgs e)
{
backgroundWorker1.CancelAsync();
}
In order to receive a callback on Exited event, the EnableRaisingEvents must be set to true.
Process correctionProcess = Process.Start(startInfo);
correctionProcess.EnableRaisingEvents = true;
correctionProcess.Exited += new EventHandler(ProcessExited);
Using exited worked well for me and gave me great flexibility to either run sequentially, partially concurrently, or all at once - without locking the UI.
Perhaps you should implement a solution with the BackgroundWorker. It is easy to implement and does what you want.
What you have to do is add an instance of a BackgroundWorker in your form, and make the call to the Process running the App.exe from the BackgrondWorker RunWorkerAsync method. Then on you can monitor for a CancelationPending property to stop the process or RunWorkerCompleted event to perform whatever is necessary after the Process has exited.
There is another SO question, concerning the BackgroundWorker cancelation
the solution for this is using a multi-threading start by adding:
using System.Threading;
then look at the code bellow :
Process process = new Process();
process.StartInfo = new ProcessStartInfo("app.exe");
process.StartInfo.WorkingDirectory = "";
process.StartInfo.Arguments = "some arguments";
//starts a new thread that starts the process so when you call WaitForExit it does not freez the main thread
Thread th= new Thread(() =>
{
process.Start();
process.WaitForExit();
});
th.Start();
if you want to run multiple process back to back it is another case you will need to use something like a List of process look at the code bellow
List<Process> processes = new List<Process>();;
Process process = new Process();
process.StartInfo = new ProcessStartInfo("app.exe");
process.StartInfo.WorkingDirectory = "";
process.StartInfo.Arguments = "some arguments";
processes.Add(process);
// i add another one manually but you can use a loop for exemple
Process process2 = new Process();
process.StartInfo = new ProcessStartInfo("app.exe");
process.StartInfo.WorkingDirectory = "";
process.StartInfo.Arguments = "some arguments";
processes.Add(process2);
// then you will start them though your thread and the 2nd process will wait till the first finishes without blocking the UI
Thread th= new Thread(() =>
{
for (int i = 0; i < processes.Count; i++)
{
processes[i].Start();
processes[i].WaitForExit();
}
});
th.Start();
来源:https://stackoverflow.com/questions/1728099/visual-c-sharp-gui-stops-responding-when-process-waitforexit-is-used