如何实现在C#中的进度条?(How do I implement a progress bar in

2019-06-18 08:17发布

如何实现在C#中的数据库调用一个进度条和BackgroundWorker的?

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

我想用进度栏或状态条的标签,但由于只有一个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);
}

我在寻找更好的例子。

Answer 1:

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

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;
}

选取框风格需要启用VISUALSTYLES,但它自身的不断滚动,而无需进行更新。 我使用的不报告其进度的数据库操作。



Answer 2:

如果你不知道的进展,你不应该滥用进度条假的,而不是仅仅显示了某种类似en.wikipedia.org/wiki/Throbber#Spinning_wheel忙图标的启动任务时,它显示和隐藏它时,它的完了。 这将使一个更“老实” GUI。



Answer 3:

当您执行在后台线程操作,并且您想更新UI,你不能打电话或设置从后台线程什么。 在WPF的情况下,你需要Dispatcher.BeginInvoke和WinForms的情况下,你需要调用方法。

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);
    });
}

的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);
    });
}

对于的WinForms代表可能需要一些铸造或你可能需要一些帮助那里,现在不记得确切的语法。



Answer 4:

报告背后与后台工作进展的想法是通过发送“已完成百分比”事件。 你是你自己负责确定莫名其妙“多少”工作已经完成。 很不幸,这往往是最困难的部分。

在你的情况下,大部分工作是数据库相关的。 目前就我所知,没有办法直接从数据库中获取进度信息。 你可以尝试但做的,是动态拆分工作。 例如,如果你需要阅读大量的数据,一个简单的方式来实现,这可能是。

  • 确定有多少行被检索(SELECT COUNT(*)FROM ...)
  • 鸿沟较小的块的实际读数,每一个块结束时报告进展:

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


Answer 5:

因为它是为一个概念证明我还没有编译这一点。 这就是我已经实现了在过去的数据库访问一个进度条。 这个例子显示了访问使用System.Data.SQLite模块SQLite数据库

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{   
    // Get the BackgroundWorker that raised this event.
    BackgroundWorker worker = sender as BackgroundWorker;
    using(SQLiteConnection cnn = new SQLiteConnection("Data Source=MyDatabase.db"))
    {
        cnn.Open();
        int TotalQuerySize = GetQueryCount("Query", cnn); // This needs to be implemented and is not shown in example
        using (SQLiteCommand cmd = cnn.CreateCommand())
        {
            cmd.CommandText = "Query is here";
            using(SQLiteDataReader reader = cmd.ExecuteReader())
            {
                int i = 0;
                while(reader.Read())
                {
                    // Access the database data using the reader[].  Each .Read() provides the next Row
                    if(worker.WorkerReportsProgress) worker.ReportProgress(++i * 100/ TotalQuerySize);
                }
            }
        }
    }
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.progressBar1.Value = e.ProgressPercentage;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Notify someone that the database access is finished.  Do stuff to clean up if needed
    // This could be a good time to hide, clear or do somthign to the progress bar
}

public void AcessMySQLiteDatabase()
{
    BackgroundWorker backgroundWorker1 = new BackgroundWorker();
    backgroundWorker1.DoWork += 
        new DoWorkEventHandler(backgroundWorker1_DoWork);
    backgroundWorker1.RunWorkerCompleted += 
        new RunWorkerCompletedEventHandler(
    backgroundWorker1_RunWorkerCompleted);
    backgroundWorker1.ProgressChanged += 
        new ProgressChangedEventHandler(
    backgroundWorker1_ProgressChanged);
}


Answer 6:

这将Helpfull.Easy落实,100%测试。

for(int i=1;i<linecount;i++)
{
 progressBar1.Value = i * progressBar1.Maximum / linecount;  //show process bar counts
 LabelTotal.Text = i.ToString() + " of " + linecount; //show number of count in lable
 int presentage = (i * 100) / linecount;
 LabelPresentage.Text = presentage.ToString() + " %"; //show precentage in lable
 Application.DoEvents(); keep form active in every loop
}


文章来源: How do I implement a progress bar in C#?