为什么使用BackgroundWorker.ReportProgress会出现TargetInvocationException?

3
我正在处理一个C#项目,在其中我有一个Backgroundworker来执行我的“耗时任务”。
在我的“DoWork”中,我想通过“backgroundworker.ReportProgress(some int)”来报告进度。但是当我的程序调用“backgroundworker.ReportProgress(some int)”时,我会收到一个“System.Reflection.TargetInvocationException”的错误。
我该如何解决这个问题?
private void btnGrap_Click(object sender, EventArgs e)
    {
        //some code
        ListsObject listsObject = new ListsObject(filePaths, enumList);
        progressBar1.Maximum = 100;//count;
        this.bgrndWorkerSearchMatches.RunWorkerAsync(listsObject);
     }

_DoWork:

private void backgroundWorkerSearchMatches_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < 100; i++)
        {
            bgrndWorkerSearchMatches.ReportProgress(i);
        }
     }

_ProcessChanged:

private void bgrndWorkerSearchMatches_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        //progressBar1.Value = e.ProgressPercentage;
    }

我找到了答案:

我使用Visual Studio创建了backgroundworker事件处理程序,但不知道我必须手动设置:

bgrndWorkerSearchMatches.WorkerReportsProgress = true;

您可能希望将调试器设置为在所有异常发生时中断。 - SLaks
3个回答

9

当最终调用的方法抛出不同的异常时,会抛出TargetInvocationException来包装它。

检查InnerException以了解发生了什么。


我尝试了以下代码:try { bgrndWorkerSearchMatches.ReportProgress(count); } catch (System.Reflection.TargetInvocationException tiEx) { throw tiEx.InnerException; }但是在内部异常之前抛出了异常。 - scro
不要 throw InnerException,它会破坏堆栈跟踪。相反,在调试器中查看 InnerException。 - SLaks

2

找到了答案:

我用 Visual Studio 创建了 BackgroundWorker 事件处理程序,但不知道我必须手动设置:

bgrndWorkerSearchMatches.WorkerReportsProgress = true;

无论如何,非常感谢大家。


1

你没有说明 ReportProgress() 到底是做什么的,但你需要调用该命令。

我猜它会是这样的:

private void ReportProgress(int percentage)
{
  this.SetProgressBar(percentage);
}

然后在设置工作线程的“父”代码中:

delegate void SetProgressBarCallback(int percentage);
public void SetProgressBar(int percentage)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.progressBar1.InvokeRequired)
            {   
                SetProgressBarCallback d = new SetProgressBarCallback(SetProgressBar);
                this.Invoke(d, new object[] { percentage});
            }
            else
            {
                this.progressBar1.value = precentage;
            }
        }

请看这里,其中有一个使用WinForms的例子。


如果您需要后台操作报告其进度,可以调用ReportProgress方法来引发ProgressChanged事件。http://msdn.microsoft.com/en-us/library/ka89zff4.aspx - scro
如果您使用它来触发进度条位置的更改,仍需要检查并使用回调函数来更新UI。 - ChrisBD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接