【发布时间】:2015-06-09 13:58:56
【问题描述】:
我正在尝试在读取文件时更新进度条。 文件大小在 200Kb 到 50Mb 之间变化。
我使用 System.ComponentModel.BackgroundWorker 进行读取过程,具有以下定义:
progressBar.Minimum = 0
progressBar.Maximum = System.IO.FileInfo.Length(我不关心百分比)。
阅读过程:
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bg = sender as BackgroundWorker;
while (!reader.EndOfStream)
{
line = reader.ReadLine();
file_content.Add(line);
progress_precentage += line.Length + 2;
System.Threading.Thread.Sleep(100);
bg.ReportProgress(progress_precentage);
}
}
以及更新过程:
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
labelProgress.Content = "reading " + e.ProgressPercentage + " out of " + file_length + " bytes";
}
UI 的反应很奇怪。 对于 300Kb 的文件,进度条和标签甚至都没有更新。它们立即达到最大值。 对于 50Mb 的文件,它们会在一秒钟内完成更新 4 次。
所以我添加了 System.Threading.Thread.Sleep:
while (!reader.EndOfStream)
{
line = reader.ReadLine();
file_content.Add(line);
progress_precentage += line.Length + 2;
System.Threading.Thread.Sleep(100);
bg.ReportProgress(progress_precentage);
}
这导致 300Kb 文件大约需要一分钟才能完成,而 50Mb 文件......你明白了。
当我使用 System.Threading.Thread.Sleep(1) 时,300Kb 的文件以非常快的速度运行了大约一半,实际上速度变慢了,直到大约 5 秒后完成。 50Mb 的文件需要很长时间才能完成。
当然,我可以摆弄 Thread.Sleep,让它每 10 行左右触发一次,但性能会根据文件大小而变化。
有没有办法考虑文件大小,以便无论文件大小如何,该过程都会在 2~3 秒内完成?我知道这是可能的,因为读取一个 50Mb 的文件只需不到一秒的时间就可以完成(没有 Thread.Sleep)。
谢谢!
编辑: 建议后的代码(由于某种原因无法将其作为答案提交):
void worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bg = sender as BackgroundWorker;
try
{
file_content = System.IO.File.ReadAllLines(file_path).ToList();
}
catch ()
{
bg.ReportProgress(-1);
file_read_successful = false;
return;
}
//For i from 0 to 100
System.Threading.Thread.Sleep(10);
bg.ReportProgress(i);
file_read_successful = true;
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
//Failure to read file
if (e.ProgressPercentage < 0)
{
//Show popup with failure message
textBlockFailure.Text = (string)e.UserState;
popupSelect.IsOpen = true;
return;
}
labelProgress.Content = e.ProgressPercentage + "%";
progressBar.Value = e.ProgressPercentage;
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (file_read_successful)
{
labelProgress.Content = "Done!";
progressBar.Value = progressBar.Maximum;
}
else
{
labelProgress.Content = "";
progressBar.Value = progressBar.Minimum;
}
//Unregister events
worker.DoWork -= worker_DoWork;
worker.ProgressChanged -= worker_ProgressChanged;
worker.RunWorkerCompleted -= worker_RunWorkerCompleted;
}
【问题讨论】:
-
如果您真的想放慢速度以便用户可以看到一个漂亮的进度条,我建议您将文件加载进度与进度条分开。减慢文件加载速度有什么意义?只需加载文件而不对其进行限制,然后每半秒左右更新一次进度条。
-
感谢您的回复,这是一个有效的解决方案,因为弄清楚如何准确地限制文件读取将是复杂且耗时的。我很快就会发布我的实现。
标签: wpf progress-bar backgroundworker