【问题标题】:Background worker - report progress with string array后台工作人员 - 使用字符串数组报告进度
【发布时间】:2011-03-28 12:48:14
【问题描述】:

我需要在每个循环中从我的后台工作人员返回多个 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
}

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

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

【问题讨论】:

  • 您运行backgroundWorker2 但报告backgroundWorker1 是否有更深层次的原因?
  • 另外,为什么使用字符串数组而不是集合?
  • 对不起,我的错误。示例错误,现在应该是正确的。

标签: c# .net backgroundworker


【解决方案1】:

您的代码 sn-p 无法重现该问题。一个标准错误是调用 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);
        }

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

【讨论】:

    【解决方案2】:

    当您实例化 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);
                }
            }
    

    【讨论】:

    • WorkerReportsProgress 已经为真,我需要报告 MULTIPLE STRING 值,返回一个值对我有用,但是当我尝试返回数组时,出现错误。
    • 好吧,你只要多次调用报告进度:worker.ReportProgress(10, "Message1"); worker.ReportProgress(11, "Message2");
    • 这有点解决了我的问题,但也创建了一个新问题,因为我正在使用 progressBar.PerformStep() 更新每个 ReportProgress() 上的进度条。
    • 如果您不想更新(例如,如果没有进度),只需在两条消息上传递相同的进度,例如:worker.ReportProgress(10, "Message1"); worker.ReportProgress(10, "Message2");
    【解决方案3】:

    我已经解决了一个类似的问题,方法是向后台工作人员添加一个新的 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;
    }
    

    【讨论】:

    • 您也可以尝试使用 Monitor 代替 while(progressed),在我的情况下它对我不起作用!
    • 对不起,但没必要像 Hans_passant 那样伤心,你所要做的就是在循环中插入字符串数组实例化
    猜你喜欢
    • 2010-10-25
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多