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();