【问题标题】:Refresh progress bar刷新进度条
【发布时间】:2015-06-14 09:32:02
【问题描述】:

我想刷新 C# WPF 中的进度条。

这个问题听起来很简单,我应该可以用谷歌搜索它。但是我看到的解决方案让我不满意。

假设我必须运行一个很长的算法,例如5个不同的步骤。 我不知道计算不同的步骤需要多长时间。 但我知道我已经编写了什么程序,我可以使用分析器来检查 CPU 用于每个步骤的时间(以所有步骤总时间的百分比)。

这可能是时代例如:

Method1() takes 3s
Method2() takes 5s
Method3() takes 1s

这是我的方法:

“简单”的方法:

ProgressBar pb = new ProgressBar()
                     {
                         // The total duration of all methods
                         Maximum = 9
                     };

Method1();
// + 3 for 3 seconds
pb.Value += TimeForMethod1;

Method2();
// + 5 for 5 seconds
pb.Value += TimeForMethod2;

Method3();
// + 1 for 1 second
pb.Value += TimeForMethod3;

这很容易。但是有问题。这会阻塞我的 UI 线程 9 秒,这太可怕了(因为用户可能认为程序崩溃了)。

所以使用线程似乎很明显..


“线程”方法:
这有一个问题,我需要调度 ProgressBar 上的每个操作,这可能非常慢(对于 ProgressBar 上的大量更新)

我为此写了一个“任务队列”。我可以将我想做的所有工作保存在 Queue 中,Thread 在调用 Run 并更新任务之间的 ProgressBar(和 Label)之后正在处理所有这些任务。

我不想发布ThreadQueue 的所有代码,因为它已经实现了很多而且可能还没有那么好实现(还)。

这是线程方法的重要部分:

foreach (var threadQueueNode in threadQueue)
{
    // Changes e.g. a label displaying what the thread is doing next
    threadQueueNode.PreMainFunction.Invoke();

    // Executes the main task
    this.Result = threadQueueNode.MainFunction.Invoke();

    // Updates the ProgressBar after the work is done.
    threadQueueNode.PostMainFunction.Invoke();
}

PostMainFunction 是 Delegate 和例如这个:

PostMainFunction = (Action<int>)((value) => this.Dispatcher.Invoke(() => this.ProgressBarStatus.Value += value));

对于像我这样的问题,更新 ProgessBar 的专业方法是什么?
我很乐意讨论。

感谢您的帮助和时间!

【问题讨论】:

  • 为什么不使用Background Worker?

标签: c# wpf multithreading progress-bar


【解决方案1】:

BackgroundWorker 清晰易读:

var bw = new BackgroundWorker();

bw.DoWork += (s, e) =>
{
    var worker = s as BackgroundWorker;
    Method1();
    worker.ReportProgress(30);
    Method2();
    worker.ReportProgress(80);
    Method3();
    worker.ReportProgress(100);
};

bw.ProgressChanged += (s, e) =>
{
    pb.Value += e.ProgressPercentage;
};

bw.RunWorkerCompleted += (s, e) => 
{ 
};

bw.RunWorkerAsync();

【讨论】:

  • 你能解释一下后台工作者和线程之间的区别吗?在我看来,区别在于 BG 有一些事件,如“WorkCompleded”和其他东西。
  • @JensHorstmann 你的区别在于托管线程和适当的事件,正如我提到的那样,它干净易读。
【解决方案2】:

问题是我需要调度 ProgressBar 上的每个操作,这可能非常慢

解决方案是预先计算对进度条的更改,仅在需要时调用 UI 线程并更新图形。

例如,您有 100.000 次操作。您不需要更新进度条 100.000 次。无论如何,用户都不会注意到差异。为每个百分比更新一次(在本例中为 1000 条记录),以便在每个百分比上通知用户。每隔几秒更新一次 UI 就可以了。

【讨论】:

  • 嗯,我也想过这个问题。但是我的“线程方法”是正确的方法吗?还是有更好的?
猜你喜欢
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 2014-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-14
相关资源
最近更新 更多