2011-07-23 30 views
7

Tôi đã tìm thấy một mã an toàn trên web và đã sửa đổi nó một chút để xem cách hoạt động, nhưng bây giờ tôi gặp sự cố với ContinueWhenALl vì nó không chờ đợi tất cả các công việc sẽ được hoàn thànhContinueWhenAll không đợi tất cả công việc để hoàn thành

List<Task> tasks = new List<Task>(); 
for (int i = 0; i < 20; i++) 
{ 
    int j = i; 
    var compute = Task.Factory.StartNew(() => results.Add(DoSomething(j))); 
    tasks.Add(compute); 
} 

Tôi đang sử dụng mã này để thêm tất cả công việc vào danh sách. DoSomething chức năng tính toán một số kết quả và thêm chúng vào BlockingCollection Tôi có một chức năng hiển thị mà viết tất cả kết quả bổ sung từ BlockingCollection để an ủi

Tôi đã sử dụng mã này để chờ đợi cho tất cả các nhiệm vụ để hoàn thành nhưng có vẻ như nó không chờ đợi chúng như chương trình hiển thị thông báo "Nhấn phím bất kỳ để tiếp tục" tiêu chuẩn chỉ sau vài mili giây sau khi chương trình đã được bắt đầu. (Nó sẽ mất ~ 20 giây cho chương trình để hoàn thành)

Task.Factory.ContinueWhenAll(tasks.ToArray(), result => results.CompleteAdding()); 

Tuy nhiên nếu tôi thêm Task.WaitAll(consume) đến cuối chương trình, chương trình hoạt động tốt

var consume = Task.Factory.StartNew(() => display(results)); 
//results = BlockingCollection that I mentioned 

Viễn như tôi hiểu nó chương trình sẽ không có đủ thời gian để hiển thị tất cả kết quả từ BlockingCollection nhưng vẫn còn đủ thời gian để hiển thị một số trong khi chờ đợi cho tất cả các nhiệm vụ được hoàn thành

Có thể ai đó giải thích cho tôi tại sao Task.Factory.ContinueWhenAll không chờ tất cả kết quả được tính toán và chương trình kết thúc giống như không có dòng mã nào trong chương trình (sau vài mili giây)

Trả lời

15

Task.Factory.ContinueWhenAll không phải là phương pháp chặn; nó sẽ thực sự bắt đầu một nhiệm vụ mới sẽ chỉ hoạt động khi tất cả các tác vụ được cung cấp hoàn thành ở đó, vì vậy nó là bình thường khi thấy một vài mili giây sau khi chương trình được bắt đầu, bởi vì nó sẽ không khối khi bạn chờ đợi chính các nhiệm vụ để hoàn thành. Từ msdn:

Tạo tiếp tục Nhiệm vụ sẽ bắt đầu khi hoàn thành một tập hợp các tác vụ được cung cấp.

Trường hợp Task.WaitAll sẽ khối ở người gọi chờ đợi cho tất cả các nhiệm vụ được cung cấp để hoàn thành thực hiện.

+0

"khi hoàn thành một tập hợp các nhiệm vụ được cung cấp" đó là chính xác những gì tôi đang nói về, nó không nên tạo nhiệm vụ mới cho đến khi tất cả các nhiệm vụ từ danh sách đã hoàn thành công việc của nó. Điều khó hiểu duy nhất ở đây là chương trình chờ "trên dòng đó" hay chương trình đi đến dòng tiếp theo và khởi chạy nhiệm vụ mới sau khi hoàn thành tất cả các nhiệm vụ? – Dan

+0

@Dan: Khi 'ContinueWhenAll' Chương trình sẽ không 'chờ trên dòng đó' thay vào đó nó sẽ đi đến dòng tiếp theo và đồng thời tạo một tác vụ mới sẽ không hoạt động cho đến khi các tác vụ được cung cấp kết thúc. nhưng 'WaitAll' _ sẽ đợi trên line_" block "đó cho đến khi tất cả các nhiệm vụ được cung cấp hoàn thành ở đó. –

+0

Có vẻ như điều này không thực sự đúng, hãy xem liên kết của anh ấy http://blogs.msdn.com/b/csharpfaq/archive/2010/06/18/parallel-programming-task-schedulers-and-synchronization-context .aspx? PageIndex = 2 và bạn sẽ tìm thấy một phần nói rằng tôi đã sử dụng phương thức ContinueWhenAll đợi một mảng nhiệm vụ hoàn thành. – Dan

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