BackgroundWorker调用ReportProgress抛出TargetInvocationException问题求解
问题原因及修复方案
核心问题点
ReportProgress方法要求传入的进度百分比范围必须是 0~100,你当前直接传入单文件的行号i,如果文件行数超过 100,传入值就会超出合法范围,后续给进度条赋值时会触发越界异常。- 进度计算逻辑完全错误:你没有统计所有待处理文件的总行数,仅按单文件的行号上报进度,无法反映整体任务进度;同时
ProgressChanged事件中你用了+=累加进度值,即使百分比正确,累加操作也会导致进度条值很快超过最大值触发异常。 - 你后续把整个业务逻辑用
Invoke包裹到 UI 线程执行,完全失去了BackgroundWorker后台线程处理的意义,同时还会导致线程调度冲突,进一步触发异常。 - 如果没有显式将
backgroundWorker1.WorkerReportsProgress属性设置为true,调用ReportProgress方法会直接抛出异常。
修复方案
步骤1:调整业务逻辑
预先统计所有待处理文件的总行数作为计算整体进度的分母,上报进度时将已处理行数换算为0~100的合法百分比,移除错误的Invoke包裹逻辑。
步骤2:替换代码
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { string terms; StringBuilder sb = new StringBuilder(); int totalProcessed = 0; int totalLines = 0; if (string.IsNullOrEmpty(filePath)) return; string[] fpath = filePath.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); // 预统计所有文件的总行数 foreach (string path in fpath) { if (!string.IsNullOrEmpty(path) && File.Exists(path)) { totalLines += File.ReadAllLines(path).Length; } } // 逐行处理并上报进度 foreach (string path in fpath) { if (string.IsNullOrEmpty(path) || !File.Exists(path)) continue; string[] lines = File.ReadAllLines(path); for (int i = 0; i < lines.Length; i++) { terms = lines[i]; if (terms.Contains("Content to look for")) { sb.AppendLine(lines[i]); } totalProcessed++; // 换算为0~100的合法百分比 int progress = totalLines == 0 ? 0 : (int)((double)totalProcessed / totalLines * 100); backgroundWorker1.ReportProgress(progress); } } // 处理结果可存入e.Result,在RunWorkerCompleted事件中读取 e.Result = sb.ToString(); }
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { // 直接赋值不要累加 progressBar1.Value = e.ProgressPercentage; lblPercent.Text = $"{e.ProgressPercentage} %"; }
步骤3:开启进度上报配置
初始化backgroundWorker1时显式开启进度上报权限:
backgroundWorker1.WorkerReportsProgress = true;
内容的提问来源于stack exchange,提问作者Lee
相关产品推荐
相关产品推荐

