背景工作者 - 报告与字符串数组的进展

时间:2011-03-28 12:48:15

标签: c# .net backgroundworker

我需要在每个循环中从我的backgroundworker返回多个STRING值,所以我尝试使用ReportProgress第二个参数作为字符串数组。代码示例:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    string[] workerResult = new string[2];
    for (int i=0; i<someNumber; i++)
    {
        //do some heavy calculating
        workerResult[0] = "this string";
        workerResult[1] = "some other string";
        backgroundWorker1.ReportProgress(i, workerResult) // also tried workerResult[] and [2]
    }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    string[] results = (string[])e.UserState;

    MessageBox.Show(results[0]); // line of error
    MessageBox.Show(results[1]); // line of error
}

它编译,但在运行时我尝试访问Userstate返回的字符串,我收到一个错误:“对象引用未设置为对象的实例。”

对我来说,似乎在将数组参数传递给ProgressChanged委托时出错,或者在尝试设置结果数组值时在ProgressChanged方法中出错。

3 个答案:

答案 0 :(得分:18)

您的代码段无法重现问题。标准错误是调用ReportProgress()然后继续修改对象。事件处理程序运行需要一段时间,它将看到修改后的对象,而不是原始对象。您可以通过简单地创建一个新对象来避免这种情况,以便事件处理程序始终使用原始对象。像这样:

        //do some heavy calculating
        for (int i = 0; i < 2; ++i) {
            string[] workerResult = new string[2];
            workerResult[0] = "this string";
            workerResult[1] = "some other string";
            backgroundWorker1.ReportProgress(i, workerResult);
        }

注意如何在循环内移动数组创建语句。

答案 1 :(得分:7)

当您实例化BackgroundWorker时,您必须将reportprogress设置为true:

worker = new BackgroundWorker { WorkerReportsProgress = true };

在do work方法上你只需要这个:

 worker.ReportProgress(10, "Message");

然后这样的事情来抓住进展:

private void WorkerProgressChanged(object sender, ProgressChangedEventArgs e) {
            if (e.UserState != null) {
                MessageBox.Show(e.UserState);
            }
        }

答案 2 :(得分:0)

我通过向后台工作程序添加一个新的ProgressChanged事件侦听器解决了类似的问题,如果ProgressChanged未被触发,则阻止传递到下一个循环:

bool progressed;

backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
string[] workerResult = new string[2];
for (int i = 0; i < 2; ++i) {
    progressed=true;

    workerResult[0] = "this string";
    workerResult[1] = "some other string";
    backgroundWorker1.ReportProgress(i, workerResult);
    while (progressed)
    {
       //you can add a thread sleep 
    }
}


void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
     progressed = false;
}