2012-12-31 45 views
5

Tôi đang viết một ứng dụng mà tôi có Quy trình đang chạy trong số BackgroundWorker. Tôi muốn hỗ trợ hủy bỏ từ giao diện người dùng, nhưng tôi không thấy một cách dễ dàng để làm điều này.Hủy quá trình bắt đầu qua System.Diagnostics.Process.Start()

Process thực sự là một dòng lệnh chạy khá dài. Đầu ra được chuyển hướng không đồng bộ qua sự kiện Progress.OutputDataReceived và đang được sử dụng để báo cáo tiến trình cho 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??? 
} 

Dường như không phải là một cách để có quá trình "lắng nghe" đối với bất kỳ đầu vào từ các chủ đề chính sang một bên từ StandardInput, nhưng điều đó sẽ không làm việc trừ khi ứng dụng riêng của mình sẽ đáp ứng với một cụ thể đầu vào để hủy bỏ.

Có cách nào để hủy quy trình dựa trên yêu cầu hủy khỏi chuỗi chính không?

Vì mục đích của EXE đang chạy trong quy trình, tôi chỉ có thể gọi Process.Close() để thoát mà không có bất kỳ tác dụng phụ nào, nhưng đối tượng Process chỉ được biết đến phương pháp worker_DoWork(), vì vậy tôi sẽ cần theo dõi trong ví dụ Process vì mục đích hủy ... đó là lý do tôi hy vọng có thể có cách tốt hơn.

(nếu vấn đề, tôi đang nhắm mục tiêu NET 3.5 cho vấn đề tương thích.)

+1

Có một lý do bạn đang bắt đầu một quá trình trong một công nhân BG? Nó thường là một cuộc gọi mà không mất một thời gian dài (chương trình được đưa ra có thể mất một lúc để tải, nhưng đó sẽ là trong quá trình riêng của nó). – keyboardP

+0

Nó thực sự không phải trong một nhân viên nền, nhưng trong một phương pháp Async tùy chỉnh, 'BackgroundWorker' có vẻ đơn giản hơn để mô tả tình hình. Nhưng lý do là đây là một phần của một quá trình lớn hơn đang chạy trong một chủ đề nền. – psubsee2003

+0

CancelAsync sẽ không hoạt động vì chuỗi đã hoàn thành công việc của mình trong vài phần nghìn giây, trừ khi bạn có tải trọng nặng trong phương thức 'DoWork'. Mặc dù 'using' là thực hành tốt, vì bạn cần có khả năng truy cập vào' Process' từ nơi khác trong mã, bạn có thể có một biến cấp lớp để giữ 'Process' và gọi' Process.Close' trên đó. Chỉ cần nhớ gọi là 'Vứt bỏ' trên quy trình khi luồng của bạn trả về hoặc quá trình này không còn cần thiết nữa. – keyboardP

Trả lời

3

Đối hủy hợp tác, bạn cần phải nghe BackgroundWorker.CancellationPending trong sự kiện 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

Đề xuất tốt, tuy nhiên vì 'while (true)', vòng lặp không bao giờ thoát trừ khi nhận được hủy. Tôi đã thay đổi nó thành 'while (! Process.HasExited)' và nó hoạt động hoàn hảo, cảm ơn. – psubsee2003

-1

thử điều này, điều này có thể giúp bạn, dễ cách

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

Tôi không thấy, cách 'xử lý' bị Killed trong phương thức' Dispose'. Làm thế nào nó có thể hoạt động? – Tilak

Các vấn đề liên quan