2012-12-31 16 views
5

Piszę aplikację, w której mam proces uruchomiony w BackgroundWorker. Chciałbym wspierać anulowanie z interfejsu użytkownika, ale nie widzę łatwego sposobu na to.Anulowanie procesu rozpoczętego za pośrednictwem System.Diagnostics.Process.Start()

W rzeczywistości Process jest dość długa z linii poleceń exe. Dane wyjściowe są przekierowywane asynchronicznie przez zdarzenie Progress.OutputDataReceived i są używane do raportowania postępu w interfejsie GUI.

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    using (var process = new Process()) 
    { 
     //... 

     process.Start() 

     //... 

     process.WaitForExit(); 
    } 
} 

private void CancelWorker() 
{ 
    worker.CancelAsync(); 
    // where to actually listen for the cancellation??? 
} 

Nie wydaje się być sposobem na proces „słuchać” dla każdego wejścia z głównego wątku oprócz StandardInput, ale to nie będzie działać, chyba że sama będzie odpowiedzią na specyficzne app wejście do przerwania.

Czy istnieje sposób na anulowanie procesu na podstawie żądania anulowania z głównego wątku?

Do celów mój z EXE uruchomiony w procesie, mogę po prostu zadzwonić Process.Close() aby wyjść bez żadnych skutków ubocznych, ale obiekt Process wiadomo jedynie metody worker_DoWork(), więc będę musiał śledzić instancji Process dla celów anulowania ... dlatego mam nadzieję, że może być lepszy sposób.

(jeśli ma to znaczenie, jestem kierowanie .NET 3.5 do problemów z kompatybilnością.)

+1

Czy istnieje powód, dla którego rozpoczęcie procesu w pracownika BG? Zazwyczaj jest to połączenie, które nie zajmuje dużo czasu (uruchomienie programu może trochę potrwać, ale będzie to działać we własnym procesie). – keyboardP

+0

W rzeczywistości nie działa on w tle, ale w niestandardowej metodzie asynchronicznej "BackgroundWorker" wydawał się prostszy w opisywaniu sytuacji. Ale powodem jest to, że jest to część większego procesu, który działa w wątku w tle. – psubsee2003

+0

Funkcja AnulujAsynchronizacja nie będzie działać, ponieważ wątek zakończył pracę w ciągu kilku milisekund, o ile nie ma dużego obciążenia w ramach tej metody "DoWork". Chociaż "używanie" jest dobrą praktyką, ponieważ musisz mieć możliwość uzyskania dostępu do "Procesu" z dowolnego miejsca w kodzie, możesz mieć zmienną na poziomie klasy, która będzie utrzymywać "Proces" i wywoływać w nim "Process.Close". Pamiętaj tylko, aby wywołać "Dispose" w procesie, gdy twój wątek powróci lub proces nie jest już potrzebny. – keyboardP

Odpowiedz

3

Kooperatywnego odwołania, trzeba posłuchaj BackgroundWorker.CancellationPending w wydarzeniu BackgroundWorker.DoWork .

How to: Use a Background Worker

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    using (var process = new Process()) 
    { 
     //... 

     process.Start() 

     //... 
     while(true) 
     { 
      if ((sender as BackgroundWorker).CancellationPending && !process.HasExited) 
      { 
       process.Kill(); 
       break; 
      } 
      Thread.Sleep(100); 
     } 

     process.WaitForExit(); 
    } 
} 
+0

Dobra sugestia, jednak z powodu 'while (true)', pętla nigdy nie kończy się, dopóki nie zostanie odebrane anulowanie. Zmieniłem go na 'while (! Process.HasExited)' i działa idealnie, dzięki. – psubsee2003

-1

spróbować, może to być pomóc w łatwy sposób

private System.Threading.TimerCallback worker; 
private System.Threading.Timer workertimer ; 
private void worker_DoWork() 
{ 
    //You codes 
} 
private void StartWorker() 
{ 
    worker = new System.Threading.TimerCallback(worker_DoWork); 
    workertimer = new System.Threading.Timer(worker, null, 1000, 1000); 
} 

private void CancelWorker() 
{ 
    worker.Dispose(); 
} 
+2

Nie widzę, jak "proces" jest zabijany metodą "Wyrzuć". Jak to działa? – Tilak

Powiązane problemy