2009-10-08 27 views
15

Tôi biết rằng Task Parallel Library vẫn đang ở giai đoạn Beta và có khả năng ít tài nguyên hơn nhưng từ bất cứ điều gì tôi đã đọc, thư viện sẽ xử lý rất đặc biệt task scheduling , exception handlingcancellation.Hỗ trợ báo cáo tiến độ và kết quả gia tăng trong .NET 4.0 "Thư viện song song công việc"

Nhưng tôi không tìm thấy bất kỳ tham chiếu nào đến báo cáo tiến độgửi kết quả gia tăng từ các tác vụ. Hai điều này dường như quá quan trọng để bỏ qua. Bạn có thể ném một số ánh sáng về cách xử lý chúng trong Thư viện song song nhiệm vụ hay tham khảo một số bài viết giải thích chúng?

+0

bất kỳ giải pháp cuối cùng nào có mã nguồn đầy đủ? – Kiquenet

Trả lời

9

dụ này cập nhật một thanh tiến trình:

using System; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

class SimpleProgressBar : Form 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new SimpleProgressBar()); 
    } 

    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 

     int iterations = 100; 

     ProgressBar pb = new ProgressBar(); 
     pb.Maximum = iterations; 
     pb.Dock = DockStyle.Fill; 
     Controls.Add(pb); 

     Task.ContinueWith(delegate 
     { 
      Parallel.For(0, iterations, i => 
      { 
       Thread.SpinWait(50000000); // do work here 
       BeginInvoke((Action)delegate { pb.Value++; }); 
      }); 
     }); 
    } 
} 

Updating a progress bar from inside a Parallel.For

+0

Bạn đang ở đâu để nhận '.Tạo' trong Task? Tôi có cùng một không gian tên được nhập và không thể tìm thấy nó. –

+0

@Nick: Có vẻ như MSFT có thể đã thay đổi lớp Task một chút giữa Task Parallel CTP và bản phát hành .NET 4.0. Tôi đề nghị thử 'ContinueWith' thay vì' Create'. –

+0

Tác vụ không có cả Tạo và Tiếp tụcWith – Praneeth

2

Các TPL không được đặc biệt hướng tới hỗ trợ giao diện người dùng, bạn có thể (vẫn) sử dụng một BackgroundWorker cho điều đó. Đối với việc gửi hoặc xử lý kết quả trung gian, có các lớp sưu tập mới (ConcurrentQueue) để hỗ trợ điều đó.

7

Không có hỗ trợ tích hợp cho điều này giống như những gì BackgroundWorker có.

Bạn có thể sử dụng SynchronizationContext trực tiếp; có một video tuyệt vời tại đây: http://www.rocksolidknowledge.com/ScreenCasts.mvc/Watch?video=TasksAndThreadAffinity.wmv

Tác giả phát triển hai giải pháp trong video này: một sử dụng SynchronizationContext và một giải pháp khác bằng cách sử dụng Task Continuations. Đối với vấn đề của bạn, tiếp tục sẽ không hoạt động, nhưng cách tiếp cận SynchronizationContext sẽ hoạt động tốt.

P.S. Nếu bạn đang tạo mã tái sử dụng, thì khi bạn capture SynchronizationContext.Current, bạn nên kiểm tra null và (nếu nó là null), hãy sử dụng SynchronizationContext mặc định được xây dựng để thay thế.

CẬP NHẬT: Tôi đã đăng mã cho số on my blog này. Giải pháp của tôi thực sự dựa trên một Task được lên lịch quay lại luồng giao diện người dùng theo số TaskScheduler sử dụng SynchronizationContext bên dưới. Không giống như câu trả lời được chấp nhận, giải pháp này sẽ làm việc cho cả WPF và Windows Forms.

+0

Tôi chỉ tạo câu trả lời mới để hiển thị ví dụ đơn giản dựa trên blog của bạn ở đó. – CallMeLaNN

8

Đây là một trong những kết quả tìm kiếm hàng đầu của tôi và vẫn không có ví dụ cho sự tiến bộ trong Task Parallel Library ngay tại đây ...

Hôm nay tôi chỉ đi qua TPL vì tôi muốn phát triển ứng dụng đa luồng mới nhưng mà không sử dụng BackgroundWorker (vì tôi đọc một nơi nào đó về nhiệm vụ với mã tốt trước đây)

Tôi biên dịch ví dụ từ câu trả lời @Stephen Cleary, liên kết của anh ấy khá phức tạp để tìm kiếm tiến trình và một số trang web khác.

Đây là ví dụ rất đơn giản để làm thế nào để làm ProgressHoàn với thread UI cách an toàn:

 TaskScheduler currentTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
     Task<string>.Factory.StartNew(() => 
     { 
      // loop for about 10s with 10ms step 
      for (int i = 0; i < 1000; i++) 
      { 
       Thread.Sleep(10); 
       Task.Factory.StartNew(() => 
       { 
        // this is a task created each time you want to update to the UI thread. 
        this.Text = i.ToString(); 
       }, CancellationToken.None, TaskCreationOptions.None, currentTaskScheduler); 
      } 
      return "Finished!"; 
     }) 
     .ContinueWith(t => 
     { 
      // this is a new task will be run after the main task complete! 
      this.Text += " " + t.Result; 
     }, currentTaskScheduler); 

Mã này sẽ hiển thị 1-1000 trong vòng 10s và sau đó nối thêm một "Hoàn tất! " chuỗi trong thanh tiêu đề biểu mẫu cửa sổ. Bạn có thể thấy rằng TaskScheduler là cách khôn lanh để tạo cập nhật an toàn giao diện người dùng bởi vì tôi nghĩ rằng nhiệm vụ được lên lịch để chạy trên chủ đề chính.

+0

Tác vụ tiến trình thực sự là một phần tử con của tác vụ chính chạy đồng bộ với chuỗi giao diện người dùng. Tôi nhận được từ đây http://www.dcomproductions.com/blog/2011/08/writing-thread-safe-event-handlers-with-the-task-parallel-library-in-net-4-0/ – CallMeLaNN

0

Để báo cáo tiến độ từ tác vụ không đồng bộ, hãy chuyển một số IProgress vào phương thức không đồng bộ. Trong phương thức, hãy gọi Report cùng với dữ liệu tiến trình. Người gọi có thể quyết định cách xử lý báo cáo tiến độ đó (ví dụ: Bỏ qua hoặc cập nhật giao diện người dùng).

+2

câu hỏi yêu cầu báo cáo tiến trình trong .NET 4.0. IProgress không được giới thiệu cho đến khi .NET 4.5. – BTownTKD

+0

Pre .NET 4.5 bạn rõ ràng có thể xác định 'giao diện công cộng IProgress ' – Graham

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