views:

1102

answers:

4

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!

+5  A: 

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
}
Konamiman
I tried that, but the code after process.Start(); is executed before app.exe finishes.
Levo
I don't quite understand what you're trying to achieve. If you want ro run some other process, you have to do it asynchronously - handling proces.Exited as Konamiman suggested. If you use process.WaitForExit() you're running code synchronously, and therefore your application will freeze.
Bolek Tekielski
I want to run process 1. WHEN it exists I want process 2 to start. And the GUI not to freeze.
Levo
Then, create and start process 1 in SomeMethod, then in the ProcessExited method, create and run process 2.
Konamiman
I thought of that before, if I don't find anything better I'll try it. The only problem is that I use a lot of "if" there, so it would be a little bit complicated.
Levo
A: 

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

Nikos Steiakakis
+2  A: 

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.

Kasprzol
+2  A: 

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();
    }
Benny
I get an error: Thread does not exist in the current context.
Levo