2010-01-19 35 views
6

Tôi có một dự án thú cưng mà tôi đang làm việc trên đó có nhiều chuỗi công việc. Xuất ra tất cả mọi thứ để bàn điều khiển là nhận được khó khăn để làm theo, vì vậy tôi muốn phát triển một giao diện người dùng sẽ có một khu vực đầu ra cho mỗi chủ đề. Tôi muốn biết cách tốt nhất cho các chủ đề để gửi cập nhật cho giao diện người dùng. Tôi có hai ý tưởng:Cập nhật giao diện người dùng từ nhiều chuỗi công việc (.NET)

1) Yêu cầu mỗi chủ đề đặt cờ "DataUpdated" khi có dữ liệu mới và yêu cầu giao diện người dùng định kỳ kiểm tra dữ liệu mới.

2) Tạo từng chủ đề có gọi lại đến phương thức Cập nhật giao diện người dùng (...) để được gọi khi có dữ liệu mới.

Tôi hiện đang nghiêng về (2) vì hai lý do: Tôi không thích ý tưởng "kiểm tra" từng chuỗi và vì đây là ứng dụng đa luồng đầu tiên của tôi và (2) có vẻ đơn giản hơn. Tôi muốn biết:

  • Tùy chọn nào là thích hợp hơn về tính đơn giản và hiệu quả?
  • Bạn có bất kỳ mẹo nào để triển khai (2) hoặc điều gì đó tương tự (ví dụ: hướng sự kiện hơn) không?

Trả lời

12

Bạn có thể dễ dàng thực hiện (2) bằng cách tạo ra các thành phần BackgroundWorker và làm việc trong xử lý DoWork của họ:

BackgroundWorker bw = new BackgroundWorker(); 
bw.WorkerReportsProgress = true; 
bw.DoWork += /* your background work here */; 
bw.ProgressChanged += /* your UI update method here */; 
bw.RunWorkerAsync(); 

Mỗi BackgroundWorker có thể báo cáo tiến đến thread UI bằng cách gọi ReportProgress: mặc dù điều này được thiết kế chủ yếu cho báo cáo tiến trình về một quy trình bị chặn, đó không phải là bắt buộc - bạn cũng có thể chuyển dữ liệu tùy chỉnh của riêng mình nếu đó là những gì cập nhật giao diện người dùng của bạn yêu cầu. Bạn sẽ gọi ReportProgress từ trình xử lý DoWork của bạn.

Điều tốt đẹp về BackgroundWorker là nó sẽ xử lý rất nhiều chi tiết về luồng chéo lộn xộn cho bạn. Nó cũng tuân theo mô hình cập nhật theo sự kiện mà bạn (đúng) thích gọi lại rõ ràng.

+2

Tuyệt vời ... cảm ơn! Bây giờ tôi chỉ phải chờ đợi để rời khỏi công việc ban ngày của mình để tôi có thể thực hiện một số chương trình thực sự. – iandisme

+0

Thực hiện công việc này trong khung Compact (3.5). – Royal

1

Tôi cũng bỏ phiếu cho # 2 nhưng với BackgroundWorkers thay vì System.Threading.Threads.

+0

Và chức năng gọi lại cần phải an toàn ... – Oded

0

Bạn có thể có chuỗi công việc của mình tăng sự kiện và có chuỗi giao diện người dùng chính thêm trình xử lý sự kiện. Bạn cần phải cẩn thận bạn không tăng quá nhiều sự kiện vì nó có thể trở nên xấu xí nếu chuỗi công nhân của bạn đang tăng nhiều sự kiện mỗi giây.

This bài viết cung cấp tổng quan nhanh.

0

Cách ưu tiên để thực hiện đa luồng trong ứng dụng của bạn là sử dụng thành phần BackgroundWorker. Thành phần BackgroundWorker sử dụng mô hình hướng sự kiện để xử lý đa luồng. Chuỗi công việc chạy trình xử lý sự kiện DoWork của bạn và luồng tạo các điều khiển của bạn chạy trình xử lý sự kiện ProgressChanged và RunWorkerCompleted của bạn.
Khi bạn cập nhật điều khiển giao diện người dùng của mình trong trình xử lý sự kiện ProgressChanged, chúng sẽ tự động được cập nhật trên chuỗi chính sẽ ngăn không cho bạn nhận được ngoại lệ nhiễu xuyên âm.

Nhìn here để biết ví dụ về cách sử dụng công việc nền.

1

Trong hầu hết các trường hợp, việc dễ nhất là sử dụng thành phần BackgroundWorker như được đề xuất trong câu trả lời của itowlson và tôi khuyên bạn nên sử dụng phương pháp đó nếu có thể. Nếu vì một lý do nào đó, bạn không thể sử dụng thành phần BackgroundWorker cho mục đích của mình, chẳng hạn như nếu bạn đang phát triển với .Net 1.1 (yikes!) hoặc với khung nhỏ gọn, thì bạn có thể cần phải sử dụng một cách tiếp cận khác:

Với điều khiển Winform, bạn phải tránh điều chỉnh các điều khiển trên bất kỳ chuỗi nào khác với chuỗi ban đầu đã tạo điều khiển. Thành phần BackgroundWorker xử lý việc này cho bạn, nhưng nếu bạn không sử dụng nó, thì bạn có thể và nên sử dụng thuộc tính InvokeRequired và phương thức Invoke được tìm thấy trong lớp System.Windows.Forms.Control. Dưới đây là một ví dụ sử dụng tài sản này và phương pháp:

public partial class MultithreadingForm : Form 
{ 
    public MultithreadingForm() 
    { 
     InitializeComponent(); 
    } 

    // a simple button event handler that starts a worker thread 
    private void btnDoWork_Click(object sender, EventArgs e) 
    { 
     Thread t = new Thread(WorkerMethod); 
     t.Start(); 
    } 

    private void ReportProgress(string message) 
    { 
     // check whether or not the current thread is the main UI thread 
     // if not, InvokeRequired will be true 
     if (this.InvokeRequired) 
     { 
      // create a delegate pointing back to this same function 
      // the Invoke method will cause the delegate to be invoked on the main UI thread 
      this.Invoke(new Action<string>(ReportProgress), message); 
     } 
     else 
     { 
      // txtOutput is a UI control, therefore it must be updated by the main UI thread 
      if (string.IsNullOrEmpty(this.txtOutput.Text)) 
       this.txtOutput.Text = message; 
      else 
       this.txtOutput.Text += "\r\n" + message; 
     } 
    } 

    // a generic method that does work and reports progress 
    private void WorkerMethod() 
    { 
     // step 1 
     // ... 
     ReportProgress("Step 1 completed"); 

     // step 2 
     // ... 
     ReportProgress("Step 2 completed"); 

     // step 3 
     // ... 
     ReportProgress("Step 3 completed"); 
    } 
} 
0

Nếu bạn đang tạo chủ đề của riêng bạn (không BackgroundWorker hoặc đề ThreadPool), bạn có thể vượt qua một phương pháp gọi lại từ chủ đề chính của bạn đó được gọi là từ các sợi nhân. Điều này cũng cho phép bạn chuyển các đối số cho hàm gọi lại và thậm chí trả về một giá trị (chẳng hạn như cờ go/no-go). Trong cuộc gọi lại, bạn cập nhật giao diện người dùng thông qua Trình điều phối mục tiêu của điều khiển:

public void UpdateUI(object arg) 
{ 
    controlToUpdate.Dispatcher.BeginInvoke(
     System.Windows.Threading.DispatcherPriority.Normal 
     , new System.Windows.Threading.DispatcherOperationCallback(delegate 
     { 
      controToUpdate.property = arg; 
      return null; 
     }), null); 
    } 
} 
Các vấn đề liên quan