2012-11-29 30 views
5

Tôi có các tác vụ khác nhau để đọc từ các tệp khác nhau và tìm một từ trong đó. Tôi đã đặt chúng vào một mảng công việc mà tôi bắt đầu với phương pháp waitAny như sau:Cách dừng tất cả các tác vụ khi một công việc được hoàn thành trong C#

foreach (string file in filesList) 
     { 
      files[i] = Task.Factory.StartNew(() => 
      { 
       mySearch.Invoke(file); 
      }); 
      i++; 
     } 
     System.Threading.Tasks.Task.WaitAny(files); 

Tôi muốn dừng lại tất cả các nhiệm vụ khác trong thời gian sớm là một trong những nhiệm vụ kết thúc (nó kết thúc khi nó sáng lập từ). Hiện tại, với sự chờ đợi, tôi có thể biết khi nào một nhiệm vụ kết thúc, nhưng tôi không biết làm thế nào tôi có thể biết cái nào đã hoàn thành và làm thế nào để dừng các nhiệm vụ khác. Cách tốt nhất để đạt được điều này là gì?

+0

Nhiệm vụ đã hoàn thành có để lại kết quả ở đâu đó không? Điều đó có thể bao gồm việc xác định nhiệm vụ. Nhiệm vụ đầu tiên để hoàn thành cũng có thể thiết lập một sự kiện, được kiểm tra bởi mỗi nhiệm vụ trong vòng lặp chính của nó, điều đó sẽ làm cho tất cả các nhiệm vụ khác thoát ra. – HABO

+0

trong mySearch.Invoke, chúng phải là một vòng lặp lặp đi lặp lại từng chữ một. Sau đó, bạn có thể thêm cờ để ngắt vòng lặp khi cờ được báo hiệu, khi bất kỳ tác vụ nào tìm thấy từ đó, bạn có thể báo hiệu cờ – ComfortablyNumb

Trả lời

2

Bạn có thể sử dụng đơn CancellationToken mà tất cả tác vụ sẽ chia sẻ. Bên trong mySearch.Invoke phương thức xác minh giá trị token.IsCancellationRequested để hủy tác vụ. Khi một số tác vụ sẽ được hoàn tất, hãy hủy những người khác qua số CancellationTokenSource.Cancel().

var tokenSource = new CancellationTokenSource(); 
var token = tokenSource.Token; 

foreach (string file in filesList) 
{ 
    // pass cancellation token to your task 
    files[i] = Task.Factory.StartNew(() => mySearch.Invoke(file, token), token); 
    i++; 
} 

Task.WaitAny(files); 
tokenSource.Cancel(); 

BTW bạn có thể buộc thẻ để ném OperationCanceledException khi nguồn bị hủy bằng cách gọi token.ThrowIfCancellationRequested()

2

Khi tạo một nhiệm vụ bạn có thể vượt qua một CancelationToken. Đặt mã thông báo này khi một trong các tác vụ hoàn tất. Điều này sẽ khiến các tác vụ còn lại với mã thông báo này đến not execute. Các tác vụ đang chạy có thể nhận được OperationCanceledException và dừng quá.

1

Tôi rất khuyên bạn nên đọc How do I cancel non-cancelable async operations? bởi Stephen Toub. Về cơ bản những gì bạn cần làm là hủy bỏ tất cả các nhiệm vụ này, nhưng hiện tại bạn không có cơ chế để hủy bỏ chúng.

Cách tiếp cận lý tưởng là tạo CancellationTokenSource trước khi foreach, chuyển số CancellationToken từ nguồn đó đến từng nhiệm vụ con, kiểm tra mã thông báo đó định kỳ và ngừng làm việc khi bạn nhận thấy nó được chỉ định hủy. Sau đó, bạn có thể hủy nguồn mã thông báo trong việc tiếp tục WhenAny.

Nếu đó không phải là tùy chọn bạn cần quyết định xem có thực sự dừng công việc hay không, hoặc nếu bạn chỉ cần tiếp tục với mã của mình mà không cần đợi chúng hoàn thành (thật dễ dàng để làm).

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