2012-07-30 91 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; 
    } 
} 
相关问题