刷新进度条

时间:2015-06-14 09:32:03

标签: c# wpf multithreading progress-bar

我想在C#WPF中刷新一个progess栏。

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

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

这可能是时间,例如:

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

这是我的方法:

" Easy"方法

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的非常多的更新)

我写了一个" TaskQueue"为了那个原因。我可以在Queue中保存我想要完成的所有工作,并且ThreadRun被调用后正在处理所有这些任务并更新ProgressBar(以及{{1}在任务之间。

我不想发布Label的所有代码,因为它非常多,也许还没有那么好实现(还)。

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

ThreadQueue

PostMainFunction是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(); } ,例如这样:

Delegate

对于像我这样的问题,更新ProgessBar的专业方法是什么?
我对讨论感到高兴。

感谢您的帮助和时间!

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

  

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

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

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