WaitforExit не работает правильно - PullRequest
3 голосов
/ 09 февраля 2012

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

По сути, мое приложение вызывает файл java для загрузки приложения на устройство.Пока он загружается, он печатает его в поле richtext, тогда я бы хотел перейти к следующему файлу.Проблема у меня заключается в том, что во время загрузки первого файла, второй пытается загрузить, какие случаи проблемы.Я попытался дождаться выхода, но если я это сделаю, то выходные данные не будут записаны в поле расширенного текста.Есть идеи?

private void btnLoad_Click(object sender, EventArgs e)
    {
        rchsdtOut.Clear();
        //count the items in queue.
        var count = lstBarToLoad.Items.Count;

        if (count <= 0)
        {
            MessageBox.Show("Nothing added to the load queue");
       }
        else
       {

            String toLoad;
            for (int i=0; i < count;i++)
              {//START OF FOREACH
                 toLoad = lstBarToLoad.Items[i].Text;
                //call load method.
                  loaddPB(toLoad);      
              }//end of for.
        }//end of else.
    }//end of private

Я пытался поместить ожидание выхода во многих местах, но, похоже, это не сработало.

     //Method to load files on device.
    private void loaddPB(string toLoad)
    {

        process1 = new System.Diagnostics.Process();
        process1.StartInfo.UseShellExecute = false;
        process1.StartInfo.RedirectStandardOutput = true;
        process1.StartInfo.RedirectStandardError = true;
        process1.StartInfo.CreateNoWindow = true;
        process1.StartInfo.FileName = "java.exe ";

        process1.StartInfo.Arguments = "-Xmx512M -jar";
        process1.StartInfo.Arguments += toLoad;
        try
        {

                 process1.Start();
                 process1.OutputDataReceived += (s, a) => myMethod(a);
                 process1.BeginOutputReadLine();
                 process1.ErrorDataReceived += (s, a) => myErrorMethod(a);
                 process1.BeginErrorReadLine();

                 process1.WaitForExit();
        }
        catch
        {
            Console.WriteLine("error");
        }

    }

Два метода ниже пишут stdout или ошибкув поле richtext.

        //Method to do the logging.
    private void myMethod(DataReceivedEventArgs e)
    {

            if (e.Data != null)
            {
                Action action = () => rchsdtOut.Text += "\r\n" + e.Data.ToString();
                rchsdtOut.BeginInvoke(action, null);
                Console.WriteLine(e.Data.ToString());
            }

    }//end of private

    //Method to load the error if any thrown.
    private void myErrorMethod(DataReceivedEventArgs e)
    {
        if (e.Data != null)
        {
            Action action = () => rchsdtOut.Text += "\r\n" + e.Data.ToString();
            rchsdtOut.BeginInvoke(action, null);
            Console.WriteLine(e.Data.ToString());

        }
    }//end of private

Любые идеи будут великолепны.По сути, мне нужен процесс для выхода, поэтому я могу продолжить, подумав, forloop для загрузки следующего файла.

Ответы [ 4 ]

6 голосов
/ 09 февраля 2012

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

Вам нужно запустить процесс "в фоновом режиме", чтобы ваш пользовательский интерфейс продолжал обновляться. Это можно сделать с помощью:

  • Запускать и контролировать процесс из отдельного потока и передавать информацию о ходе выполнения обратно в поток пользовательского интерфейса для отображения
  • Добавьте обработчик события в событие exited процесса или периодически опрашивайте флаг process.HasExited и используйте его, чтобы узнать, когда завершился первый процесс. Ваш обработчик событий запустит этот процесс, а затем выйдет обратно в основной цикл приложения, чтобы он работал как обычно, ожидая завершения внешнего процесса.
  • Сядьте в занятый цикл ожидания до его завершения и обработайте события приложения. (Остерегайтесь этого, так как любые события, которые вызывают повторные входящие вызовы этого кода, могут сделать очень плохие вещи. Обычно, если вы используете этот подход, вы должны убедиться, что остальная часть вашего приложения "заблокирована" в состоянии, в котором оно знает это занят ожиданием завершения процесса). Это фактически то, что делает WaitForExit, но он также обрабатывает события приложения, позволяя пользовательскому интерфейсу оставаться неопределенно отзывчивым:

    while (!process.HasExited)  
    {  
        Application.DoEvents();  
        Thread.Sleep(100);  
    }
    
0 голосов
/ 30 января 2014

Как рекомендовано здесь , настройка process.EnableRaisingEvents = true решила проблему заблокированного пользовательского интерфейса в моем случае.

0 голосов
/ 09 февраля 2012

Попытка вывести вызов WaitForExit из потока пользовательского интерфейса.

Как @M.Бэбкок упоминал, что вы задерживаете обновления в расширенном текстовом поле.

Решение, подобное этому, может работать:

Изменить btnLoad_Click, чтобы запустить новый поток, который обрабатывает список (это происходитв подсчете> 0 филиал)

Thread thread = new Thread(new ThreadStart(LoadPbThread));
thread.Start();

Затем добавьте это:

void LoadPbThread()
{
    String toLoad;
    for (int i=0; i < count;i++)
    {//START OF FOREACH
        toLoad = lstBarToLoad.Items[i].Text;
        //call load method.
        loaddPB(toLoad);      
     }//end of for.
}
0 голосов
/ 09 февраля 2012

Я могу быть совершенно не прав, но ...

process1.StartInfo.Arguments = "-Xmx512M -jar";
process1.StartInfo.Arguments += toLoad;

Вам нужно иметь пробел после -jar

Или Javaсобирается немедленно бомбить.

...