c#progressbar没有更新

时间:2010-08-02 11:00:53

标签: c# wpf progress-bar ui-thread

我有一个ProgressBarWindow,它上面有一个进度条和一个取消按钮,用于报告文件I / O的进度。但是,尽管在后台工作中完成了所有工作,但ProgressBarWindow的UI线程和我的主窗口都会挂起。进度条呈现,就像我的主窗口一样,但是在后台工作人员执行其操作时不会更新。 在主窗口的构造函数的最后调用以下代码:

iCountLogLinesProgressBar = new ProgressBarWindow();
iCountLogLinesProgressBar.cancelButton.Click += EventCountLogLinesProgressBarCancelButtonClicked;
iCountLogLinesProgressBar.Show();

iCountLogRecords = new BackgroundWorker();
iCountLogRecords.DoWork += EventCountLogLinesDoWork;
iCountLogRecords.ProgressChanged += EventCountLogLinesProgressChanged;
iCountLogRecords.RunWorkerCompleted += EventCountLogLinesRunWorkerCompleted;
iCountLogRecords.WorkerReportsProgress = true;
iCountLogRecords.WorkerSupportsCancellation = true;
iCountLogRecords.RunWorkerAsync(new BinaryReader(File.Open(iMainLogFilename, FileMode.Open, FileAccess.Read)));

EventCountLogLinesProgressChanged()如下所示:

private void EventCountLogLinesProgressChanged(object sender, ProgressChangedEventArgs e)
{
    iCountLogLinesProgressBar.Value = e.ProgressPercentage;
}

这是ProgressBarWindow的缩短版本(其余只是几个制定者):

public partial class ProgressBarWindow : Window
{
    public ProgressBarWindow()
    {
        InitializeComponent();
        this.progressBar.Value = this.progressBar.Minimum = 0;
        this.progressBar.Maximum = 100;
    }

    public double Value
    {
        get
        {
            return progressBar.Value;
        }
        set
        {
            this.progressBar.Value = value;
        }
    }
} 

我已经尝试在dispatcher.invoke委托中包装值setter行但是这给了我一个堆栈溢出(我不应该有一个dispatcher.invoke行,因为backgroundworker在UI Thread中调用ProgressChanged,对吧? )。我已经检查了msdn并用谷歌搜索了但我似乎无法找到其他任何有这个问题的人。

编辑道歉,我没有意识到我的简化代码阻止了UI线程,尽管使用了后台工作者,但我得到了完全相同的行为,所以我错误地认为它们是等效的。我应该提到我正在使用背景工作者:P

2 个答案:

答案 0 :(得分:14)

您正在阻止UI线程,因此在循环完成之前它不会重新呈现UI。

将后台处理移动到单独的线程中,并使用适当的Dispatcher调用(或BackgroundWorker)将UI更新调用封送回UI线程。

如果您的进度条确实只是一个计时器,您可以使用其中一个Timer类来更新它。

编辑:好的,现在你已经改变了代码,看起来对我来说没问题。它应该是线程安全的,因为您只是在UI线程上更改UI。你的后台工作人员肯定会定期报告进度吗?

答案 1 :(得分:3)

听Jon Skeet, 或者您有时可以调用Application.DoEvents()在同一个线程中进行所有UI更新。