2012-07-30 90 views
0

我創建了一個表單,當我打電話給我一個耗時的例程時,彈出並顯示進度條。我通過UpdateProgress方法提供我的例程進度。Backgroundworker ProgressChanged在工作完成後執行

我正在使用後臺工作人員來允許用戶移動窗體並在此窗體更新時繼續進行業務。但是,表單只會鎖定,直到例程完成,然後快速將進度條上升到100%並退出(如應該)。進度條應該與正在對UpdateProgress方法進行調用的進程一起更新。

我在這裏做錯了什麼?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Threading; 

namespace myNameSpace 
{ 
    public partial class ProgressIndicator : Form 
    { 
     int progressPercentage; 

     public ProgressIndicator() 
     { 
      InitializeComponent(); 
     } 

     void progressUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      // update the UI with appropriate fields 
      progressBar.Value = e.ProgressPercentage; 
      labelCommunicating.Text = "In progress: " + e.ProgressPercentage + "% complete"; 
     } 

     void progressUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      this.Close(); 
     } 

     void progressUpdater_DoWork(object sender, DoWorkEventArgs e) 
     { 
      BackgroundWorker worker = sender as BackgroundWorker; 

      while (true) 
      { 
       if (progressPercentage >= 100) 
       { 
        break; 
       } 

       worker.ReportProgress(progressPercentage); 

       Thread.Sleep(100); 
      } 
     } 

     public void UpdateProgress(int progressPercentage) 
     { 
      this.progressPercentage = progressPercentage; 
     } 

     private void ProgressIndicator_Load(object sender, EventArgs e) 
     { 
      BackgroundWorker progressUpdater = new BackgroundWorker(); 
      progressUpdater.WorkerReportsProgress = true; 
      progressUpdater.WorkerSupportsCancellation = true; 
      progressUpdater.DoWork += new DoWorkEventHandler(progressUpdater_DoWork); 
      progressUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(progressUpdater_RunWorkerCompleted); 
      progressUpdater.ProgressChanged += new ProgressChangedEventHandler(progressUpdater_ProgressChanged); 

      progressUpdater.RunWorkerAsync(); 
     } 
    } 
} 
+1

沒有任何方式可以讓您發佈的代碼重現問題。您在DoWork中使用Sleep(),這將永遠隱藏問題。但真正的DoWork事件處理程序經常會經常調用ReportProgress。 UI線程越快,它就會開始落後。如果時間夠頻繁,而且沒有完成其低優先級任務。就像迴應用戶輸入或繪製控件一樣。它會看起來死。人類只能以每秒25次的速度看到進展,*方式*少於淹沒UI線程所需的時間。 – 2012-07-30 22:52:29

+0

咦?完成「工作」(DoWork處理程序)時,您不會更新進度。另外,您不會顯示如何調用UpdateProgress的示例。通常「進展」表示已完成工作;這是由DoWork處理程序完成的。 – 2012-07-30 23:18:46

+0

Hans:添加了睡眠,以便應用程序不佔用資源。彼得:工作在其他地方完成,「DoWork」方法在這裏執行的是檢查進度並相應地更新屏幕。 'UpdateProgress'方法改變了進度。 – Kashif 2012-07-31 02:58:16

回答

1

這聞起來像一個牽強的解決方案,我認爲你的問題在於while loop。但是,更好的方法可能是通過使用Invoke();來簡單地更新您的ProgressBar而不阻止UI。

Invoke(new myUpdate(updateProgress), pval);//call invoke whenever you need to update the progress bar assuming pval is an integer with the value to update with. This could be in a thread for instance. 

//declare this as a class level delegate 
private delegate void myUpdate(int progress); 

//method to update progress bar 
private void updateProgress(int progress) 
{ 
    progressBar.Value = progress; 
} 
+0

謝謝你的迴應!這似乎比我想要做的要好得多。 我在第一行發現錯誤,它說'updateProgress'。它說'updateProgress'在當前上下文中不存在。 – Kashif 2012-07-30 22:27:04

+0

有一點小錯誤,但現在已更新。確保所有方法和委託和調用位於您正在更新進度的表單類中。 – 2012-07-30 22:41:35

+0

我正在接聽另一班的電話。我怎樣才能使代碼正確的做到這一點? – Kashif 2012-07-30 22:43:04

0

您可以用這種方式創建流程,而不需要將您的調用包裝在Invoke方法中。

//delegate method 
private delegate void updateProgressDelegate(int progress); 

//actual method 
private void updateProgress(int progress) 
{ 
    if(this.InvokeRequired) 
    { 
     this.Invoke(new updateProgressDelegate(updateProgress), progress); 
    } 
    else 
    { 
     progressBar.value = progress; 
    } 
} 
相關問題