我想创建一个专用的类来更新我的应用程序中的进度条(在本例中是WPF进度条)。我做了这样的事:
public class ProgressBarUpdate : IDisposable
{
private readonly double _delta;
private int _current;
private int _total;
private readonly ProgressBar _pb;
public ProgressBarUpdate(ProgressBar pb, int total)
{
_pb = pb;
_total = total;
// the pb.Maximum is a double so it doesn`t get truncated
_delta = _pb.Maximum / total;
_current = 0;
_pb.Visibility = Visibility.Visible;
}
public void Dispose()
{
_pb.Visibility = Visibility.Collapsed;
_current = 0;
}
public void UpdateProgress()
{
_pb.Value =(int)_delta * (++_current);
}(在UI线程中):
using (var pu = new ProgressBarUpdate(pb, totalCount)
{
for (x=0; x<totalCount; x++)
{
// operations here
pu.UpdateProgress()
}
}但是UI可能被阻止了,但没有正确地更新。什么是显示所有进展的最佳方式?
发布于 2013-07-29 21:16:04
Winforms/WPF程序是一个Eventing系统。只有一个线程连续地处理事件队列中的事件。这是它的主要工作,理想的是,这是它应该做的唯一的事情。任何类型的UI活动都会在事件队列中生成事件--就像您将鼠标移到窗口上,或者单击某个或某些其他窗口重叠您的窗口,然后当它离开重叠位置时再次发生。所有这些事件都由UI线程处理,这使UI始终保持更新。
此外,Winforms/WPF只允许在UI线程上访问和/或更新控件及其属性,从而以线程安全的方式进行访问。
如果阻止此UI线程或在其上执行其他CPU绑定计算,则您的UI响应性和更新的行为将受到影响。最坏的情况下UI会冻结。
因此,正确的答案是对另一个工作线程执行计算循环,并且只通过使用Dispatcher封送对UI线程的调用来更新进度条UI。
然而,为了回答你的问题和满足你的调查,这里有一些是可能的--但这是坏实践,您应该永远不要做以下事情
简单地说,当您更新进度条的Value属性时,它会使进度条UI失效-所以UI必须更新。因此,假设在事件队列中生成了一个事件,这将导致一些代码运行,从而更新UI。但是,您正在UI线程上运行一个循环--因此,除非您的循环结束,否则线程没有机会处理此事件。因此,您看不到任何UI更新。诀窍是在对进度条的Value进行下一次更新之前,让UI线程处理该事件。您可以通过在事件队列中强制调用一个较低优先级的项来做到这一点--以便在进入下一次迭代之前处理正常和更高优先级的项。
using (var pu = new ProgressBarUpdate(pb, totalCount))
{
for (int x = 0; x < totalCount ; x++)
{
// operations here
pu.UpdateProgress();
Dispatcher.Invoke(DispatcherPriority.Background, new Action(()=>{}));
}
}https://stackoverflow.com/questions/17925632
复制相似问题