C#进度条在进度完成一半后才更新
我正在使用C#进度条在进度完成一半后才更新,c#,.net,wpf,progress-bar,dispatchertimer,C#,.net,Wpf,Progress Bar,Dispatchertimer,我正在使用Dispatchermer更新progressBar的值: DispatcherTimer tim = new DispatcherTimer(); tim.Interval = TimeSpan.FromMilliseconds(100); tim.Tick += delegate { if (valuee < max) { prog.Value = valuee; } else { tim.Stop();
Dispatchermer
更新progressBar的值:
DispatcherTimer tim = new DispatcherTimer();
tim.Interval = TimeSpan.FromMilliseconds(100);
tim.Tick += delegate
{
if (valuee < max)
{
prog.Value = valuee;
}
else
{
tim.Stop();
}
};
但是由于某些原因,progressBar直到超过一半的迭代结束才更新!怎么了?队列在Dispatcher
线程上工作,该线程是WPF UI线程
以下是MSDN关于计时器执行的说明:
在每个调度程序循环的顶部重新评估调度程序。
计时器不保证在时间间隔出现时准确执行,但保证在时间间隔出现之前不执行。这是因为Dispatcher操作与其他操作一样放置在Dispatcher队列上。调度程序操作的执行时间取决于队列中的其他作业及其优先级
您正在经历进度计时器的延迟,因为您很可能正在运行一个长阻塞操作,该操作拒绝处理不同请求的messageloop
您有两个选择:
循环代码打开一个文件,然后在
for
循环中增加进度(valuee
)。似乎while
循环读取到文件的末尾。然后,for循环的保持,同时
确保它仍然处于EOF状态,因为没有打开新文件。(我假设Input
和fsInput
应该是同一个变量。)
BackgroundWorker
线程上的ReportProgress
/ProgressChanged
机制是处理从后台工作线程更新UI的跨线程复杂性的可靠方法。您可以使用来传递其他信息,例如当前正在处理以显示在标签中的文件的名称。在哪个线程上运行什么代码?在for
循环中还会发生什么?块3位于另一个线程上是否有原因避免在BackgroundWorker
线程上使用ReportProgress
/ProgressChanged
机制?更新进度条和状态显示对我来说效果很好。循环代码打开一个文件,然后在for
循环中增加进度(valuee
)。似乎while
循环读取到文件的末尾。然后,for
循环的保持,同时
确保它仍然处于EOF状态,因为没有打开新文件。(我假设Input
和fsInput
应该是同一个变量。)@HABO将您的评论作为答案发布,以便我可以接受!你能添加它的代码吗?我想看看你是怎么称呼它的。尚未正确格式化,但我仍发布了itI。我希望看到对后台线程的调用,而不是在内部运行的委托。看起来不错。您的UI线程中还有其他事情吗?我刚刚注意到:valuee只更新了一次,等待了很长时间,然后开始正常工作。但是for循环中的其余代码不会停止一次!
using (FileStream fs = File.Open(Filename, FileMode.Open))
{
if (fs.Length > 10485760 && fs.Length <= 209715200)
prog.Maximum = fs.Length / 1024;
else if (fs.Length <= 10485760)
prog.Maximum = fs.Length / 16;
else if(fs.Length > 209715200)
prog.Maximum = fs.Length / 1048576;
}
var Input = File.OpenRead(path);
int Size = MainWindow.prog.Maximum;
for (long i = 0; i < Input.Length; i += Size)
{
MainWindow.valuee++;
PasswordEnter.valuee++;
byte[] chunkData = new byte[chunkSize];
int bytesRead = 0;
while ((bytesRead = fsInput.Read(chunkData, 0, chunkSize)) > 0)
{
if (bytesRead != chunkSize)
{
for (int x = bytesRead - 1; x < chunkSize; x++)
{
chunkData[x] = 0;
}
}
cryptoStream.Write(chunkData, 0, bytesRead);
}
}
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (obj, l) => lo.Encrypt(Filename, password.Password, "main");
worker.RunWorkerAsync();