2

我有一个 Windows 程序正在对数据库进行一些更新。它有 2 个循环,我想展示其进度。第一个循环获取客户列表,第二个循环获取该客户的位置列表:

DataTable dtCustomers = GetAllCustomers();

foreach(DataRow customer in dtCustomers.Rows)
{
    //update Customer Progressbar...

    //do some updating here...

    DataTable dtLocations = GetAllLocations(customer);

    foreach(DataRow location in dtLocations.Rows)
    {
        //do some updating here...

        //update Location Progressbar...
    }

    //reset Location Progressbar...
}

所以我想做的是显示每个循环的视觉进度条(pb)。客户 pb 将随着每个处理的客户而增加,位置 pb 也会增加......唯一的区别是位置 pb 将在每个位置之后重置,因为根据位置更新可能需要更长/更短的时间。

我从 1 个后台工作人员开始,并且能够很好地更新客户 pb。我将以下代码放在“开始”按钮中:

private void buttonStart_Click(object sender, EventArgs e)
{
    workerCustomers.RunWorkerAsync();
}

在 workerCustomer 的 DoWork() 事件中,我放置了 2 个循环。我知道位置 pb 不会更新,因为它会给出“跨线程引用”错误。那么我该如何去做我想做的事呢?我什至尝试在表格上放置 2 个 bg 工作人员并从另一个调用一个,但再次出现另一个错误,说明第一个工作人员很忙。

4

1 回答 1

4

当您报告进度时,您可以传递额外的 userState 对象作为第二个参数(请参阅ReportProgress方法定义):

workerCustomers.ReportProgress(percentage1, percentage2);

ProgressChanged事件处理程序中,您可以更新两个进度条:

void workerCustomers_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage; // Customers
    progressBar2.Value = (int)e.UserState; // Locations
}

更新:如何在您的情况下使用它

DataTable dtCustomers = GetAllCustomers();
int customerIndex = 0;

foreach(DataRow customer in dtCustomers.Rows)
{
    //do some updating here...
    int customerPercentage = ++customerIndex * 100 / dtCustomers.Rows.Count;
    workerCustomers.ReportProgress(customerPercentage, 0);

    int locationIndex = 0;
    DataTable dtLocations = GetAllLocations(customer);

    foreach(DataRow location in dtLocations.Rows)
    {
        //do some updating here...
        int locationPecentage = ++locationIndex * 100 / dtLocations.Rows.Count;
        workerCustomers.ReportProgress(customerPercentage, locationPecentage);
    }

    workerCustomers.ReportProgress(customerPercentage, 0);
}
于 2012-10-24T20:52:25.467 回答