如何在C#中实现进度条?

20 .net c# winforms progress-bar

如何在C#中实现数据库调用的进度条和后台工作程序?

我确实有一些处理大量数据的方法.它们是相对较长时间运行的操作,所以我想实现一个进度条让用户知道实际发生了什么.

我想过使用进度条或状态条标签,但由于有一个UI线程,执行数据库处理方法的线程,UI控件没有更新,使得进度条或状态条标签对我来说没用.

我已经看过一些例子,但它们处理for循环,例如:

for(int i = 0; i < count; i++)
{ 
    System.Threading.Thread.Sleep(70);
    // ... do analysis ...
    bgWorker.ReportProgress((100 * i) / count);
}

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = Math.Min(e.ProgressPercentage, 100);
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找更好的例子.

Kyl*_*net 18

有些人可能不喜欢它,但这就是我的意思:

private void StartBackgroundWork() {
    if (Application.RenderWithVisualStyles)
        progressBar.Style = ProgressBarStyle.Marquee;
    else {
        progressBar.Style = ProgressBarStyle.Continuous;
        progressBar.Maximum = 100;
        progressBar.Value = 0;
        timer.Enabled = true;
    }
    backgroundWorker.RunWorkerAsync();
}

private void timer_Tick(object sender, EventArgs e) {
    if (progressBar.Value < progressBar.Maximum)
        progressBar.Increment(5);
    else
        progressBar.Value = progressBar.Minimum;
}
Run Code Online (Sandbox Code Playgroud)

Marquee样式需要启用VisualStyles,但它会不断滚动,无需更新.我将其用于不报告其进度的数据库操作.

  • 图形用户界面组件用于表示含义,进度条用于表示"完成了多少任务",即"进度".虽然你肯定不是唯一一个这样做的人,如果你不知道进展你不应该通过滥用进度条来伪造它,而只是显示某种繁忙的图标,如http://en.wikipedia.org/ wiki/Throbber#Spinning_wheel在启动任务时显示它并在完成时隐藏它.这将使一个更"诚实"的GUI. (18认同)

use*_*727 11

如果你不知道进展你不应该通过滥用进度条来伪造它,而只是显示某种繁忙的图标,如en.wikipedia.org/wiki/Throbber#Spinning_wheel在启动任务时显示它并在它的时候隐藏它完了.这将使一个更"诚实"的GUI.


Aka*_*ava 6

当您在后台线程上执行操作并且您想要更新UI时,您无法从后台线程调用或设置任何内容.对于WPF,您需要Dispatcher.BeginInvoke,如果是WinForms,则需要Invoke方法.

WPF:

// assuming "this" is the window containing your progress bar..
// following code runs in background worker thread...
for(int i=0;i<count;i++)
{
    DoSomething();
    this.Dispatcher.BeginInvoke((Action)delegate(){
         this.progressBar.Value = (int)((100*i)/count);
    });
}
Run Code Online (Sandbox Code Playgroud)

的WinForms:

// assuming "this" is the window containing your progress bar..
// following code runs in background worker thread...
for(int i=0;i<count;i++)
{
    DoSomething();
    this.Invoke(delegate(){
         this.progressBar.Value = (int)((100*i)/count);
    });
}
Run Code Online (Sandbox Code Playgroud)

对于WinForms委托可能需要一些演员或你可能需要一点帮助,不记得现在的确切语法.


jer*_*enh 5

向后台工作人员报告进度的想法是通过发送'完成百分比'事件.你自己负责确定已经完成了多少"工作量".不幸的是,这通常是最困难的部分.

在您的情况下,大部分工作与数据库相关.据我所知,无法直接从DB获取进度信息.然而,你可以尝试做的是动态地分解工作.例如,如果您需要阅读大量数据,可以采用一种天真的方式来实现这一点.

  • 确定要检索的行数(SELECT COUNT(*)FROM ...)
  • 将实际读数除以较小的块,每次完成一个块时报告进度:

    for (int i = 0; i < count; i++)
    {
        bgWorker.ReportProgress((100 * i) / count);
        // ... (read data for step i)
    }
    
    Run Code Online (Sandbox Code Playgroud)