2011-06-01 80 views
4

我正在学习winforms,并为自己设定了一个简单的目标,即让进度条从空到满。这里是我的畸形尝试:在C#中实现进度条的正确方法

public partial class Form1 : Form 
{ 
    static BackgroundWorker bw = new BackgroundWorker(); 

    public Form1() 
    { 
     InitializeComponent(); 
     bw.DoWork += bw_DoWork; 
     bw.RunWorkerAsync(); 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     for(int i=0; i<100; ++i) 
     { 
      progressBar1.PerformStep(); 
      Thread.Sleep(10); 
     } 
    } 
} 

我敢肯定的是,Thread.Sleep()是应该受到谴责的。我在这里如何避免它?

+0

尝试[这里](http://stackoverflow.com/questions/2168192/progressbar-separate-thread)。或[这里](http://stackoverflow.com/questions/1946377/c-progressbar-problem)。或[这里](http://stackoverflow.com/questions/336553/how-to-display-progressbar-if-waithandle-is-used)。 – 2011-06-01 16:49:54

+0

或者如果你想做一些兴奋尝试运行一个算法,并使用StopWatch对象来衡量一个步骤从该算法,比你可以计算多少次步骤将被执行,所以你可以得到TotalTime,并基于该使用你'数学技能以获得当前阶段的百分比,所以我认为这将满足你是老师。 – Burimi 2011-06-01 21:51:56

回答

7

你已经在做它几乎正确。 BackgroundWorker已经建立了报告进度的机制。

public Form1() 
{ 
    bw1.WorkerReportsProgress = true; 
    bw1.ProgressChanged += bw1_ProgressChanged; 
    bw1.DoWork += bw1_DoWork; 

    bw1.RunWorkerAsync(); 
} 

private void bw1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    var worker = sender as BackgroundWorker; 

    while (workNotDone) 
    { 
     //Do whatever work 
     worker.ReportProgress(CalculateProgressDonePercentage()); 
    } 
} 

private void bw1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    //This is called on GUI/main thread, so you can access the controls properly 
    progressBar.Value = e.ProgressPercentage; 
} 

当然,除非你只是想以动画的进度条实际上不报告任何进展,在这种情况下,你应该只使用Marquee类型,它会自动滚动进度没有做任何事情。或者仅使用Thread.Sleep()的后台线程。

3

在后台线程中,调用Thread.Sleep没有任何问题。
如果这是一个占位符,您可以安全地将其替换为实际工作。

但是,您不能直接从后台线程操纵ProgressBar(或任何其他控件)。
相反,您应该使用BackgroundWorker的内置进度功能来控制进度栏。

如果您只是想为无意义的progressbasr设置动画效果,则应该使用WinForms Timer而不是BackgroundWorker

1

如果你只是想做一个耗时的任务测试更新界面,Thread.Sleep没问题。对于非平凡的程序,您总是会找到一些任务来完成。

但是,您不应该直接更新BackgroundWorker.DoWork中的进度条,因为Windows要求必须在UI线程上调用更新UI,而不是后台UI。相反,请拨打BackgroundWorker.ReportProgress方法。始终更新BackgroundWorker.ProgressChanged事件中的UI。

您couls在这里看到的例子:http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx