在表单加载时使用进度条

本文关键字:表单 加载 | 更新日期: 2023-09-27 18:18:55

我正在尝试在c#中设计一个WinForms控件,它将在加载时从数据库中获取一些数据。

我想用进度条来显示进度。

我尝试了以下代码(以及其他许多代码):

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    this.Show();
    
    progressBar1.Value = 10;
    int n;
    n = 50;//number of records in DB ,
    double progress = 0;
    double progstep = 25 / n;
    for (int i = 1; i <= n; i++)
    {
        //getting 
        if (progress <= 100)
            progressBar1.Value = (int)progress;
    }
    progressBar1.Value = 35;
    n = 100;//number of records in DB for another data reading from DB ,
    progress = 35;
    progstep = 65 / n;
    for (int i = 1; i <= n; i++)
    {
        //getting data from DB
        dataGridView1.Rows.Add(....);
        //Adding that data to a datagrid -- parametrs removed.
        progress += progress;
        if (progress <= 100)
            progressBar1.Value = (int)progress;
    }
}

但是,问题是表单将等待直到数据读取进度完成,我只能看到一个完整的进度条和所有数据加载。

我该怎么做来解决这个问题?

在表单加载时使用进度条

由于这是winforms,我建议使用BackgroundWorker。

基本例子:

bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged += new DoWorkEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerAsync(//pass in object to process)

然后启动:

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
     //Do all of your work here
     bgWorker.ReportProgress(); //percent done calculation  
}

然后触发Progress changed事件以安全地更新UI:

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
     progressBar.Value = e.ProgressPercentage;
}

添加backgroundWorker1到您的表单。

添加YourForm_Shown事件

private void YourForm_Shown(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

InitializeComponent()之后添加form的构造函数

backgroundWorker1.WorkerReportsProgress = true;
// This event will be raised on the worker thread when the worker starts.
backgroundWorker1.DoWork += new
    DoWorkEventHandler(backgroundWorker1_DoWork);
// This event will be raised when we call ReportProgress.
backgroundWorker1.ProgressChanged += new
    ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

最后加上backgroundWorker1的空:

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // The progress percentage is a property of e
    progressBar1.Value = e.ProgressPercentage;
}

:

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i <= n; i++)
    {
        //getting data from DB.
        dataGridView1.Rows.Add(....);
        //Adding that data to a datagrid -- parametrs removed.
        backgroundWorker1.ReportProgress(i);
        // Simulate long task                 
    }
}

这是一个简单的模型,向您展示如何使用后台worker:

首先在OnLoad中创建后台工作器并附加2个事件:

var bw = new BackgroundWorker();            
bw.RunWorkerCompleted +=
    new RunWorkerCompletedEventHandler(WorkCompleted);
bw.DoWork += new DoWorkEventHandler(DoWork);
bw.RunWorkerAsync(data); // Assume data is list of numbers.
private void WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
// After work completed remove event handlers and dispose.
{
    var bw = (BackgroundWorker)sender;
    bw.RunWorkerCompleted -= WorkCompleted;
    bw.DoWork -= DoWork; bw.Dispose();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
    var data = (List<int>)e.Argument;
    foreach (var number in data)
    {
        if (progressBar1.InvokeRequired)
        {
            progressBar1.Invoke((MethodInvoker)delegate
                { this.ProcessNumber(number); });                    
        }
        else
        {
            ProcessNumber(number);
        }
    }
}
private void ProcessNumber(int i)
{
    progressBar1.PerformStep();
    //do something with i
}

看看BackgroundWorker控件。

backgroundWorker.RunWorkerAsync();

和覆盖事件DoWork来做脏工作(从数据库加载数据)和ProgressChanged来更新进度条。在事件主体中(假设事件签名是这样的):

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
    var worker = (BackgroundWorker)sender;
    // time consuming operation
    worker.ReportProgress(10, null);
    // ... another stuff
    }
private void backgroundWorker_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
}