【问题标题】:WinForms not drawing ProgressBar according to its propertiesWinForms没有根据其属性绘制ProgressBar
【发布时间】:2017-07-03 12:55:33
【问题描述】:

我正在使用ProgressBar 来监控DataGridView 的人口,其中的数据从数据库中检索,并在其左侧放置了Label

这没什么特别的。数据检索发生在BackgroundWorkerDoWork 处理程序中,此时ProgressBar 采用选取框样式,而Label 显示通用“正在加载...”。加载完成后,BackgroundWorkerProgressChanged 处理程序将行一一添加到DataGridView,而ProgressBarLabel 显示进度。我为此使用的代码如下:

*code that adds row*
if (e.ProgressPercentage > 0)
    pbrProgress.Value = e.ProgressPercentage - 1;
pbrProgress.Value = e.ProgressPercentage;
lblProgress.Text = e.ProgressPercentage + "/" + pbrProgress.Maximum;

Label 总是正确显示,通过调试我发现ProgressBar 也有正确的ValueMaximum 属性。但是,ProgressBar 实际上直到达到第 10 个结果左右才开始显示进度(绿色填充)。当最后一个结果被添加到DataGridView 时,它也远未满。

图片: Beginning Near the end

我尝试在代码末尾添加pbrProgress.Refresh();,并使用自定义ProgressBar 并将DoubleBuffered 属性设置为true,但无济于事。

真的,我发现的唯一解决方案是在每次调用 ReportProgress 后让线程休眠 80 毫秒。还有比这更好的方法吗?

【问题讨论】:

标签: c# winforms progress-bar


【解决方案1】:

可能是进度条没有响应,所以它没有重绘自己。

应该在BackgroundWorkerDoWork-Event 中调用此类工作密集型内容,而不是在ProgressChanged-Event 中调用。 ProgressChanged-Event 是您要更改 ProgressBar 的地方。

所以你可以做某事。像这样:

private static void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            int size = 100;

            // Function to Setup your Progressbar
            form.SetUpProgressBar(size);

            // hard work...
            for (int i = 0; i < size; i++)
            {
                Thread.Sleep(100);

                // Fires the Worker_ProgressChanged Event with the Percentage of the current progress
                (sender as BackgroundWorker).ReportProgress(i + 1);
            }
        }

        private static void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // Update the ProgressBar
            form.progressBar1.Value = e.ProgressPercentage;
        }

        private static void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("Hey I'm done!");
        }

注意:

在你可以使用worker.ReportProgress()之前你必须调用worker.WorkerReportsProgress = true;,否则你会遇到错误。

ProgressChanged 内部的方法调用需要 Invocation(如果你不知道怎么做,请联系我)。

你应该像这样使用 BackgroundWorker:

1) DoWork 为您必须与 GUI 线程分离的繁重工作
2) ProgressChanged 向您的 ProgressBar 报告进度
3) RunWorkerComplete 表示您现在已完成(关闭 Windows 等)

您可以为 BackgroundWorker 提供一些值,如下所示:worker.RunWorkerAsync(value); 并通过DoWork-Event 中的(e.Argument as int)(或其他)访问它。

希望这会有所帮助:)

-- 麦丁

【讨论】:

    【解决方案2】:

    好吧,事实证明解决方案非常简单。

    代替

    if (e.ProgressPercentage > 0)
        pbrProgress.Value = e.ProgressPercentage - 1;
    pbrProgress.Value = e.ProgressPercentage;
    

    应该是的

    pbrProgress.Value = e.ProgressPercentage;
    if (e.ProgressPercentage > 0)
          pbrProgress.Value = e.ProgressPercentage - 1;
    

    我不知道为什么它以一种方式而不是另一种方式工作。也许是因为进度条值在第一次迭代时只改变一次?

    不管怎样,这已经不是问题了。

    【讨论】:

      【解决方案3】:

      简单:在设置ProgressBarValue 属性后添加Application.Doevents()

      【讨论】:

      • 我刚刚尝试过,但似乎没有任何明显的帮助。
      • 好的,尝试在表单上将双缓冲区设置为 true,然后在进度条上执行无效操作。还要确保您正在检查是否需要调用。
      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 2011-04-17
      • 2019-07-09
      • 2023-02-01
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多