我有一个 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 的简化版本(剩下的只是几个 setter):
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;
}
}
}
我尝试将 value setter 行包装在 dispatcher.invoke 委托中,但这给了我一个堆栈溢出(我不应该有一个 dispatcher.invoke 行,因为 backgroundworker 在 UI 线程中调用 ProgressChanged,对吧?)。我检查了 msdn 并用谷歌搜索,但我似乎找不到其他人有这个问题。
编辑道歉,我没有意识到我的简化代码阻止了 UI 线程,尽管使用了后台工作程序,但我得到了完全相同的行为,所以我错误地认为它们是等价的。我应该提到我正在使用后台工作人员:P