在我的XML编辑器中,我希望能够使用索引文件一次打开多个文件。显然,根据文件数量的不同,这可能需要一些时间,我想使用进度条来通知用户程序仍在加载并执行某些操作。 从我研究的方式来保持UI进度栏更新使用BackgroundWorker。如何让BackgroundWorker阻止UI线程?
public MainWindow()
{
InitializeComponent();
tabList = new ObservableCollection<FileTab>();
tabControl.ItemsSource = tabList;
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += backgroundWorker_DoWork;
backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;
backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
backgroundWorker.WorkerReportsProgress = true;
}
(...)
private void OpenProjectButtonClick(object sender, RoutedEventArgs e)
{
openingProgressBar.Value = 0;
openingProgressBar.Visibility = System.Windows.Visibility.Visible;
backgroundWorker.RunWorkerAsync();
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
int i = 0;
foreach (IndexFile file in indexManager.fileList)
{
this.Dispatcher.Invoke((Action)(() =>
{
tabList.Add(new FileTab(file.filePath));
}));
i++;
Console.WriteLine("-(DoWork)->" + i);
double percentage = (Convert.ToDouble(i)/Convert.ToDouble(indexManager.fileList.Count)) * 100;
Console.WriteLine("-(DoWork.percentage)-> "+ percentage);
backgroundWorker.ReportProgress((int)percentage);
}
}
void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
openingProgressBar.Value = e.ProgressPercentage;
Console.WriteLine("-(ProgressChanged)->" + openingProgressBar.Value);
}
void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
openingProgressBar.Visibility = System.Windows.Visibility.Collapsed;
backgroundWorker.Dispose();
Console.WriteLine("-(RunWorkerComplete)-> Done");
}
由于我访问的DoWork的法的标签列表我包裹在Dispathcer.Invoke这一呼吁。在这种形式下,代码类型做我想要的。它使折叠的progressBar可见并每隔一段时间更新一次。可悲的是,它不会在每次加载文件后更新百分比。从控制台中可以看到,ProgressChanged执行滞后于DoWork。根据我的理解,它在循环的每个迭代中都被调用。即使它触发了,用户界面并不总是对此作出响应。
所以我的问题是:我仍然阻止UI线程以及我怎么修复它?
这工作,现在它是如此之快,我几乎不再需要进度条了......谢谢! – Ultus
不幸的是没有为我工作。我正在报告当前循环'i',并在报告事件中将此int设置为名为'ProgressValue'的属性。这个'ProgressValue'作为值绑定到进度条。我的用户界面仍然阻塞。 – C4u
@ C4u那么改变那个怎么样? (我看不到你的问题)。在“DoWork”中执行你的工作(所有的值必须是来自你的用户界面的自治),并且每次你完成一个部分时,通过ReportProgress将它报告给你的用户界面威胁(在这里你可以使用UI值(比如'ProgressValue')如果你需要在你的UI中再做一些事情,那么当你所有的工作完成时调用'RunWorkerCompleted',我希望这会帮助你:-) – WiiMaxx