2009-07-28 4 views
9

Tôi đang làm việc trong C# và WPF, rất mới cho cả hai.Làm cách nào để hiển thị tiến trình trong một vòng lặp bận?

Tôi có một vòng lặp đọc nhiều dữ liệu từ một nguồn bên ngoài. Quá trình này mất khoảng 20 giây và tôi muốn hiển thị tiến trình cho người dùng. Tôi không cần bất kỳ thanh tiến trình ưa thích nào, vì vậy tôi đã chọn âm mưu tiến bộ của mình trong một nhãn sẽ nói "Step 1/1000", sau đó đổi thành "Step 2/1000", v.v.

Mã của tôi trông giống như điều này:

// "count" is the number of steps in the loop, 
// I receive it in previous code 

String countLabel = "/"+count.ToString(); 

for (i = 0; i < count; i++) 
{ 
    ... do analysis ... 
    labelProgress.Content = "Step "+i.ToString()+countLabel 
} 

Tuy nhiên, trong quá trình phân tích màn hình bị "kẹt" và tiến trình không hiển thị dưới dạng tiến. Tôi hiểu hành vi này từ quá khứ của tôi trong C++, nơi tôi có thể có một chuỗi riêng biệt hiển thị thanh tiến trình nhận thông báo từ vòng lặp hoặc một số hình thức repaint/refresh hoặc buộc cửa sổ/ứng dụng xử lý hàng đợi tin nhắn của nó.

Cách thích hợp để thực hiện điều đó trong C# là gì? Tôi không gắn liền với nhãn, vì vậy nếu có một màn hình tiến bộ-bar sổ popup đơn giản tôi có thể sử dụng thay vì nhãn này nó cũng sẽ là tuyệt vời ...

Cảm ơn

+0

này có thể giúp cho bạn , ** Thử nghiệm 100% ** http://stackoverflow.com/a/42995210/6863414 –

Trả lời

11

Di chuyển công việc để một BackgroundWorker và sử dụng phương thức ReportProgress.

for (i = 0; i < count; i++) 
{ 
    ... do analysis ... 
    worker.ReportProgress((100 * i)/count); 
} 

private void MyWorker_ProgressChanged(object sender, 
    ProgressChangedEventArgs e) 
{ 
    taskProgressBar.Value = Math.Min(e.ProgressPercentage, 100); 
} 
+0

Đó có phải là chủ đề an toàn không? –

+1

Có, nó phải được. Nhân viên nền của bạn chỉ có một luồng, bản cập nhật thanh tiến trình chỉ nằm trên chuỗi giao diện người dùng. Bất kỳ chủ đề nào khác ngoài chuỗi giao diện người dùng sẽ ném một ngoại lệ nếu nó cố gắng cập nhật giá trị. Vì vậy, bạn được đảm bảo an toàn luồng với phương pháp này. – user7116

2

Giao diện người dùng không được cập nhật do chuỗi hiện tại của bạn có ưu tiên cao hơn chuỗi giao diện người dùng cuối cùng sẽ đặt nhãn;). Vì vậy, cho đến khi chủ đề của bạn kết thúc, bạn sẽ cập nhật nhãn của bạn cuối cùng.

May mắn cho chúng ta, đó là một tài sản Dispatcher trên tất cả các kiểm soát WPF cho phép bạn cháy lên một chủ đề mới với ưu tiên khác ..

labelProgress.Dispatcher.Invoke(DispatcherPriority.Background, 
        () => labelProgress.Content = string.Format("Step {0}{1}", i, countLabel)); 

này lửa lên một sợi trong nền và sẽ nhận được công việc làm xong! Bạn cũng có thể thử DispatcherPriority lựa chọn khác

PS Tôi cũng mất sự tự do để thêm một phương pháp vô danh và sửa chữa chuỗi của bạn phân tích hơi .. hy vọng bạn không nhớ ..

3
//Create a Delegate to update your status button 
    delegate void StringParameterDelegate(string value); 
    String countLabel = "/" + count.ToString(); 
    //When your button is clicked to process the loops, start a thread for process the loops 
    public void StartProcessingButtonClick(object sender, EventArgs e) 
    { 
     Thread queryRunningThread = new Thread(new ThreadStart(ProcessLoop)); 
     queryRunningThread.Name = "ProcessLoop"; 
     queryRunningThread.IsBackground = true; 
     queryRunningThread.Start(); 
    } 

    private void ProcessLoop() 
    { 
     for (i = 0; i < count; i++) 
     { 
      ... do analysis ... 
      UpdateProgressLabel("Step "+i.ToString()+countLabel); 
     } 
    } 

    void UpdateProgressLabel(string value) 
    { 
     if (InvokeRequired) 
     { 
      // We're not in the UI thread, so we need to call BeginInvoke 
      BeginInvoke(new StringParameterDelegate(UpdateProgressLabel), new object[] { value }); 
      return; 
     } 
     // Must be on the UI thread if we've got this far 
     labelProgress.Content = value; 
    } 
+0

BackgroundWorker được cung cấp, do đó bạn không phải xử lý tất cả các mớ hỗn độn của sinh sản ra một sợi. – user7116

+0

@sixlettervariables Giá trị của phương pháp này là nó cho phép bạn linh hoạt hơn là chỉ chuyển một số nguyên trở lại người gọi - bạn có thể làm bất cứ điều gì (ví dụ như trả về một thông báo trạng thái) – ean5533