【问题标题】:Why is the event RunWorkerCompletedEventArgs launched before I finished loading the progress bar in its entirety?为什么在我完整加载进度条之前启动了事件 RunWorkerCompletedEventArgs?
【发布时间】:2018-03-09 13:30:17
【问题描述】:

当我运行繁重的任务或少量数据时,在任务结束时,显示百分比的label 正确达到 100% 并显示 finalized message,但即使是 progressBar 也没有加载完整的,当显示完成消息时,您可以看到完成工作的进度条动画。

我无法解决这个问题,进度条应该像我见过的所有系统一样自然地工作,进度完成,然后显示完成的消息。


这里我举个例子:

BackgroundWorker bg = new BackgroundWorker();

private void btnRun_Click(object sender, EventArgs e)
{
    bg.WorkerReportsProgress = true;
    bg.ProgressChanged += bg_ProgressChanged;
    bg.DoWork += bg_DoWork;
    bg.RunWorkerCompleted += bg_RunWorkerCompleted;
    bg.RunWorkerAsync();
    label1.Visible = true;
    progressBar1.Visible = true;
}

Dowork 事件:

private void bg_DoWork(object sender, DoWorkEventArgs e)
{
    int progress = 0, percent = 0; 
    for (int i = 0; i < ds.Tables[0].Rows.Count; i++) //Cycle that will represent the heavy task
    {
        totalRecords = ds.Tables[0].Rows.Count; 

        progress++;
        percent = Convert.ToInt16((((double)progress / (double)totalRecords ) * 100.00)); 
        System.Threading.Thread.Sleep(500);
        bg.ReportProgress(percent );
    }
}

进度改变

private void bg_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Change the value of the ProgressBar to the BackgroundWorker progress.
    progressBar1.Step = 1;
    progressBar1.Style = ProgressBarStyle.Continuous;
    progressBar1.Minimum = 0;
    progressBar1.Maximum = 100;

    if (e.ProgressPercentage > 100)
    {
        label1.Text = "100%";
        progressBar1.Value = progressBar1.Maximum;
    }
    else
    {
        label1.Text = Convert.ToString(e.ProgressPercentage) + "%";
        progressBar1.Value = e.ProgressPercentage;
    }
}

最后,在 BackgroundWorker 完成时执行的 RunWorkerCompleted 事件:

private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("Done...");
    label1.Visible = false;
    progressBar1.Visible = false;
}

如何解决这个进度条动画问题?

环境: Visual Studio 2010 (WindowsForms) 和 .NET NetFramework 4。

【问题讨论】:

  • ProgressBar 为其进度设置动画,这会产生大约 1 秒的延迟。所以你隐藏它太早了,以至于无法看到它达到 100%。原生 Windows 控件不允许禁用此动画是一个相当大的设计缺陷。你可以通过强制它向后移动来达到 99%,这不是动画。
  • 我该如何解决?真相我不知道我已经尝试了几件事并且不起作用:(,Thread.Sleep我已经放置了,所以你可以欣赏动画
  • 无法重现,即使您的代码原样(期望表数,替换为静态数字)。在我的测试中,MessageBox在bar满了并且标签显示100%后正常显示。
  • 如果你想让 Thread.Sleep() 做任何有用的事情,那么你必须把它放在 ReportProgress() 调用之后。将它放在循环中并不是很有用,只会减慢一切。
  • @Kilazur 你应该仔细观察标签,如果它达到100% 之前显示消息,但是进度条缺少一点完成,尝试放置一个固定的数字低于80或100等。

标签: c# winforms visual-studio-2010 progress-bar backgroundworker


【解决方案1】:

我认为您正面临 Windows 的 Aero 动画的经典问题。
this page 中提取的信息。

当进度条增加时会发生这种滞后。但是当进度条递减时不会发生。

所以基本上,你想要做的就是超过你应该达到的实际值,然后递减到实际值。

页面作者使用扩展方式,也可以随意做;我只是把相关代码放在这里:

// To get around the progressive animation, we need to move the 
// progress bar backwards.
if (value == pb.Maximum)
{
    // Special case as value can't be set greater than Maximum.
    pb.Maximum = value + 1;     // Temporarily increase Maximum
    pb.Value = value + 1;       // Move past
    pb.Maximum = value;         // Reset maximum
}
else
{
    pb.Value = value + 1;       // Move past
}
pb.Value = value; 

【讨论】:

  • 如何在不用创建类的情况下使用扩展方法? public static class ExtensionMethodspublic static void SetProgressNoAnimation (this ProgressBar pb, int value)
  • 你不能,但你不必这样做。您可以使用我在答案中输入的代码。
  • 准备好了!非常感谢问题解决了,你救了我的命!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
  • 2022-01-05
  • 2016-05-05
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 2018-08-16
相关资源
最近更新 更多