Графический интерфейс Visual C # перестает отвечать, когда process.WaitForExit (); используется - PullRequest
2 голосов
/ 13 ноября 2009

Я создаю приложение с графическим интерфейсом, используя Visual C # 2005 (Net Framework 2). Я использую следующий код для запуска процесса:

Process process = new Process();
process.StartInfo = new ProcessStartInfo("app.exe");
process.StartInfo.WorkingDirectory = "";
process.StartInfo.Arguments = "some arguments";
process.Start();
process.WaitForExit();

Я хочу, чтобы мое приложение дождалось завершения этого процесса, поэтому я использовал WaitForExit. Но графический интерфейс Windows зависает во время работы app.exe. Я хочу, чтобы он отвечал (например, нажмите кнопку отмены), но я не хочу, чтобы код продолжался, потому что после этого есть еще один процесс Заранее спасибо!

Ответы [ 6 ]

5 голосов
/ 13 ноября 2009

Вы можете захватить событие Exited класса Process:

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
}
4 голосов
/ 13 ноября 2009

Ваше ожидание процесса в единственном потоке вашего приложения, который также отвечает за обработку всех событий графического интерфейса. Если вы хотите дождаться какого-либо события (например, завершить какой-то другой процесс) и по-прежнему уведомлять свой код о событии, вам придется подождать другой поток или использовать обработчик события.

3 голосов
/ 13 ноября 2009

Это должно помочь. В основном для оконных форм и простых задач, таких как это, BackgroundWorker удобен. Ниже приведен простой код для запуска блокнота и ожидания его закрытия, либо пользователь может убить его, нажав кнопку отмены.

    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();
    }
2 голосов
/ 24 мая 2013

Чтобы получить обратный вызов для события Exited, EnableRaisingEvents должен иметь значение true.

Process correctionProcess = Process.Start(startInfo);
correctionProcess.EnableRaisingEvents = true;
correctionProcess.Exited += new EventHandler(ProcessExited); 

Использование exited работало для меня хорошо и давало мне большую гибкость для запуска последовательно, частично одновременно или сразу - без блокировки интерфейса.

1 голос
/ 13 ноября 2009

Возможно, вам следует реализовать решение с BackgroundWorker . Это легко реализовать и делать то, что вы хотите.

Что вам нужно сделать, это добавить в форму экземпляр BackgroundWorker и выполнить вызов Process, выполняющего App.exe, из метода BackgrondWorker RunWorkerAsync. Затем вы можете отслеживать свойство CancelationPending, чтобы остановить процесс, или событие RunWorkerCompleted для выполнения всего, что необходимо после выхода из процесса.

Есть еще один ТАК вопрос , касающийся отмены BackgroundWorker

0 голосов
/ 05 июля 2013

решение для этого заключается в использовании многопоточности начать с добавления:

с использованием System.Threading;

затем посмотрите на код ниже:

    Process process = new Process();
    process.StartInfo = new ProcessStartInfo("app.exe");
    process.StartInfo.WorkingDirectory = "";
    process.StartInfo.Arguments = "some arguments";

// запускает новый поток, который запускает процесс, поэтому при вызове WaitForExit он не блокирует основной поток

    Thread th= new Thread(() =>
    {
        process.Start();
        process.WaitForExit();
    });
    th.Start();

если вы хотите запустить несколько процессов подряд, это другой случай вам нужно будет использовать что-то вроде списка процессов, посмотрите на код ниже

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

// я добавляю еще один вручную, но вы можете использовать цикл для примера

    Process process2 = new Process();
    process.StartInfo = new ProcessStartInfo("app.exe");
    process.StartInfo.WorkingDirectory = "";
    process.StartInfo.Arguments = "some arguments";

    processes.Add(process2);

// тогда вы запустите их, хотя ваш поток и второй процесс будут ждать, пока первый завершится, не блокируя пользовательский интерфейс

    Thread th= new Thread(() =>
    {
            for (int i = 0; i < processes.Count; i++)
            {
                    processes[i].Start();
                    processes[i].WaitForExit();
             }
    });
    th.Start();
...