BackgroundWorker.ReportProgress报告错误的值

| 我有一个从大文件(100,000)行中提取字符串的类,并希望向用户提供一些进度反馈。我的问题是进度报告不正确。 我正在使用自定义类发送UserState属性:
public enum UpdateType {FileCount, ProcessedFiles, LineCount, ProcessedLines, StepUpdate};
public class ProgressUpdate
{
        public UpdateType UpdateType { get { } set { } }
        public string Update { get { } set { } }
}
这是我处理ReportProgress事件的方法:
public class BGWorkerBase : BackgroundWorker
{
    public void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        ProgressUpdate update;
        update = (ProgressUpdate)e.UserState;
        switch (update.UpdateType)
        {
            case UpdateType.FileCount:
                MainWindow.FrmDisplayProgress.FileCount = update.Update;
                break;

            case UpdateType.ProcessedFiles:
                MainWindow.FrmDisplayProgress.FileProgress = update.Update;
                break;

            case UpdateType.LineCount:
                MainWindow.FrmDisplayProgress.LineCount = update.Update;
                break;

            case UpdateType.ProcessedLines:
                MainWindow.FrmDisplayProgress.LineProgress = update.Update;
                MainWindow.FrmDisplayProgress.PrecentProgress = e.ProgressPercentage;
                break;

            case UpdateType.StepUpdate:
                MainWindow.FrmDisplayProgress.AddLine(update.Update);
                break;
        }
    }
}
MainWindow.FrmDisplayProgress是对显示进度的表单的调用。 最后,这是工人阶级:
public class TraceFile
{
    public HashSet<string> ExtractValues(HashSet<MyRegex> regexList, BackgroundWorker worker)
    {
        HashSet<string> results = new HashSet<string>();
        int rowNumber = 1;

        foreach (DataRow row in Lines.Rows)
        {
            int percentComplete = (int)(((float)rowNumber / (float)Lines.Rows.Count) * 100);
            worker.ReportProgress(percentComplete, new ProgressUpdate(UpdateType.ProcessedLines, rowNumber++.ToString()));

            // using multiple regex supports different formats for the same data type. For example - more then 1 account format
            foreach (MyRegex regex in regexList)
            {
                MatchCollection matches = regex.Matches(row[\"Text\"].ToString());
                if (matches.Count > 0)
                {
                    foreach (Match result in matches)
                        results.Add(result.ToString());
                }
            }
        }

        return results;
    }
}
这是捕获以下特定更新类型的情况:
case UpdateType.ProcessedLines:
                    MainWindow.FrmDisplayProgress.LineProgress = update.Update;
                    MainWindow.FrmDisplayProgress.PrecentProgress = e.ProgressPercentage;
                    break;
\'MainWindow.FrmDisplayProgress.PrecentProgress = e.ProgressPercentage; \'正在更新进度条。进度条不是从0缓慢地移动到100,而是从0迅速地移动到100数次。 \'MainWindow.FrmDisplayProgress.LineProgress = update.Update \'正在使用行号更新标签,但是它什么也没做。 由于某种原因,在调试模式下,我看到两者都正确更新,因此我怀疑某些线程问题。 我希望我能清楚地陈述所有这一切。 问题的解决方案: 进度条运行了几次是红色的鲱鱼,并且与问题无关。发生这种情况的原因是该方法被多次输入。 标签未更新是由于通话太频繁(有关更多详细信息,请参见下面对此问题的回答)。我将方法更改为此:
public HashSet<string> ExtractValues(HashSet<MyRegex> regexList, BackgroundWorker worker)
{
    HashSet<string> results = new HashSet<string>();
    int rowNumber = 0;
    DateTime startCount = DateTime.Now;
    DateTime endCount = DateTime.Now;

    foreach (DataRow row in Lines.Rows)
    {
        rowNumber++;
        TimeSpan timeSpan = endCount.Subtract(startCount);
        if ((timeSpan.Milliseconds > 50) | (rowNumber == Lines.Rows.Count))
        {
            int percentComplete = (int)(((float)rowNumber / (float)Lines.Rows.Count) * 100);
            worker.ReportProgress(percentComplete, new ProgressUpdate(UpdateType.ProcessedLines, rowNumber.ToString()));
            startCount = DateTime.Now;
        }

        // using multiple regex supports different formats for the same data type. For example - more then 1 account format
        foreach (MyRegex regex in regexList)
        {
            MatchCollection matches = regex.Matches(row[\"Text\"].ToString());
            if (matches.Count > 0)
            {
                foreach (Match result in matches)
                    results.Add(result.ToString());
            }
        }

        endCount = DateTime.Now;
    }

    return results;
}
已邀请:
您经常调用ReportProgress。每秒调用它的频率大约超过一千次,并且UI线程被调用请求所淹没,以至于不再处理常规任务。它停止绘画,并注意用户输入。更新仍在进行,您只是看不到它们了。 当然发生这种情况是因为您在内部循环中具有ReportProgress,并为数据集中的每一行调用了它。这是浪费的精力,人眼无法跟上更新的速度,每秒超过20次的更新看起来像是模糊。解决问题的方法是每第100行调用ReportProgress。在所有机器上都可以使用的方法是,注意经过的时间并以45毫秒为单位计数。 进度栏的问题听起来像是一个计算问题,从代码片段中看不出来。进度条起作用而不是文本更新的原因是PB旨在避免这种绘制问题,它在其Value属性更改时强制重新绘制,而不是等待Windows传递“绘制”通知。
而不是从0缓慢地移动到100 一次,进度条从0移到 快速100次。 您是否将进度条的
Minimum
Maximum
设置为0和100? WPF ProgressBar的默认值为0和1。 如果使用WinForms进度条,则默认值为0和100,这不应该是问题。

要回复问题请先登录注册