2013-09-09 3 views
4

У меня есть процесс, который работает в фоновом режиме и имеет WaitForExit(), так как продолжительность может варьироваться, и мне нужно подождать, пока она не закончится. В некоторых случаях мне нужно закончить его до его завершения, и я запускаю команду .Kill() через событие класса. Свойство .HasExited изменяется на true, но код никогда не проходит по линии WaitForExit().Does process.kill() завершает WaitForExit() (без ограничения по времени)

public class MyProcess: Process 
{ 
    private bool exited; 

    public MyProcess() 
    { 
      ... 
    } 




    public void Start(args...) 
    { 

      try 
      { 
       base.StartInfo.FileName = ... 
       base.StartInfo.Arguments = ... 
       base.StartInfo.RedirectStandardOutput = true; 
       base.StartInfo.UseShellExecute = false; 
       base.StartInfo.CreateNoWindow = true; 
       base.EnableRaisingEvents = true; 
       base.Exited += new EventHandler(MyProcessCompleted); 
       base.OutputDataReceived += new DataReceivedEventHandler(outputReceived); 
       base.Start(); 
       this.exited = false; 
       base.BeginOutputReadLine(); 

        while (!this.exited) 
        { 
         if() 
         { 
         ... 
         } 
         else 
         { 

        base.WaitForExit(); ---- after the process is killed, it never gets past this line. 

         } 

        ...      
       } 
      } 

      catch (Exception ex) 
      { 
       ...     
      } 
     } 


    private void MyProcessCompleted(object sender, System.EventArgs e) 
    { 
     exited = true; 

     ... 
    } 


    private void outputReceived(object sender, DataReceivedEventArgs e) 
    { 
      ... 
    } 


    //Subscription to cancel event 
    public void ProcessCanceled(object sender, EventArgs e) 
    { 
     ... 

     if (!exited) 
     { 
      base.Kill(); 
     } 
    } 
} 

\

UPDATE:

Мой процесс запускает клиент передачи файлов Java на основе и выполняет передачу. Процесс появляется в диспетчере задач, а Kill() не заканчивает его. Так как я действительно не забочусь о завершении процесса, а скорее нуждаюсь в моей программе, чтобы перейти к следующей «задаче», я добавил Close() сразу после Kill(), который выпускает WaitForExit и позволяет моему коду «двигаться дальше». Прекращение процесса на раннем этапе будет редким явлением в моем приложении, но мне все еще нужно его работать, поэтому эта реализация должна будет сделать.

+1

Любой код для показа? – EZI

ответ

0

Вы бы попробовали более чистый код (я думаю). тестирование .....

Process proc = null; 

//Kill process after 3 seconds 
Task.Run(() => 
{ 
    Task.Delay(3000).Wait(); 

    if(proc!=null && proc.HasExited==false) proc.Kill(); 
}); 


var psi = new ProcessStartInfo() 
{ 
    FileName = "ping.exe", 
    Arguments = "-t 127.0.0.1", 
    RedirectStandardOutput = true, 
    UseShellExecute = false, 
    CreateNoWindow = true, 
}; 

proc = new Process(); 
proc.StartInfo = psi; 
proc.OutputDataReceived += (s,e) => 
{ 
    Console.WriteLine(e.Data); 
}; 

proc.Start(); 
proc.BeginOutputReadLine(); 
proc.WaitForExit(); 

Console.WriteLine("**killed**"); 
+0

Вы действительно пытались убить «proc», пока «proc.WaitForExit()» все еще ждет? 'Console.WriteLine ("** ** убит");' может выполняться просто потому, что процесс завершился не потому, что вы его прекратили. – Felix

+0

Нет, параметр '-t', * ping * работает бесконечно. Просто закомментируйте * задачу * часть и попробуйте. – EZI

+0

ваш код работал, поэтому я заменил процесс в моем коде процессом «ping» и «.Kill();» работал. Хм, так что есть что-то, что не позволяет завершить мой процесс. Странный. – Felix

7

WaitForExit есть прямой призыв к ОС ждать ручки процесс, чтобы стать сигналом. Когда процесс завершается, WaitForExitбудет полностью. Kill - это прямой звонок TerminateProcess, который убит без вопросов. При правильном использовании WaitForExit вернется после Kill.

Так что в вашем коде есть иная ошибка. Создайте более простой репродукт, и вы увидите, что проблема исчезнет. Ошибка скрыта в сложности вашего кода.

Или, WaitForExit возвращение товара не принимается, но вы не заметили. Или, Kill никогда не выполнялся или не был выполнен. Опять же, упрощение кода покажет проблему. Можете ли вы перенести его на 5 строк? Я сомневаюсь, что вы это сделаете, но я буду смотреть снова, если вы это сделаете.

Попробуйте это:

Process p = Process.Start("notepad.exe"); 
Task.Factory.StartNew(() => { Thread.Sleep(1000); p.Kill(); }); 
p.WaitForExit(); 

Update:

В комментариях вы указали, что убийство пинг делает работу, но убивает ваш специальный процесс не делает. Причина этого обычно не отменяется. Ядро Windows поддерживает процессы до тех пор, пока не будет выполнено все IO. Хорошей новостью является то, что процесс окончательно исчезнет, ​​и код не будет запущен после того, как Kill вернется. Плохая новость заключается в том, что очистка ресурсов не полностью завершена.

Теперь вам нужно убедиться, что ваш код может двигаться, хотя WaitForExit не вернулся. Для этого я установил ManualResetEvent после завершения Kill. Вместо того, чтобы звонить WaitForExit, вы получаете дескриптор процесса, используя свойство Process.Handle, и ждите, пока одна из двух ожидающих устройств станет сигнальной. Посмотрите, что делает WaitForExit, чтобы увидеть, как вы могли бы реализовать это самостоятельно (я бы скопировал класс ProcessWaitHandle, который является внутренним).

Простым решением было бы позвонить WaitForExit(TimeSpan.FromMilliseconds(100)) в цикле и каждый раз проверять флаг exited.

+0

Я подчинил свой процесс в коде QtX выше, что достаточно просто. Процесс не прекратился, и он висел на «WaitForExit». – Felix

+0

Итак, что вы думаете о моих точках, почему этого не может быть? Я добавил код, пожалуйста, запустите его (я сделал). Вы также можете попробовать заменить имя exe для своей реальной цели, но, пожалуйста, попробуйте оба. – usr

+0

Чтение ваших комментариев У меня появилось новое подозрение и возможное решение. Я отредактировал его. Кстати, какой процесс вы начинаете? Что оно делает? – usr

Смежные вопросы