当我需要执行需要很长时间的操作时,我会在这样的BackgroundWorker中调用它,因此它不会冻结UI;
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += (s, e) => {
//Do something long lasting
for(int i = 0; i < x; i++){
//Performing action i of x
//While doing so update the progressbar
prgBar.Dispatcher.Invoke(() =>{
prgBar.Value += ((i / x) * 100.0);
});
}
};
bgWorker.RunWorkerCompleted += (s, e) => {
//Finish up things
};
bgWorker.RunWorkerAsync();
这是“走的路吗?”更新用户界面还是“未完成”? 同样的问题适用于BackgroundWorker(可能只是启动一个新线程而不是BackgroundWorker?)
答案 0 :(得分:3)
如果您需要从后台线程更新某些UI组件,则应使用Dispatcher来编组对主线程的调用。话虽如此,您似乎正在尝试更新一些进度条。 BackgroundWorker类已经为此提供了一种机制。因此,您只需在表单上使用ProgressBar控件,然后:
var bgWorker = new BackgroundWorker();
// Specify that this worker supports progress
bgWorker.WorkerReportsProgress = true;
bgWorker.OnProgressChanged += e =>
{
// This is called on the main thread. It safe to update your UI components here
myProgressBar.Value = e.ProgressPercentage;
};
bgWorker.DoWork += (s, e) =>
{
// Do something long lasting
for(int i = 0; i < x; i++) {
//Performing action i of x
// While doing so notify the subscribers of the progress event
var progress = (int)((i / x) * 100.0);
bgWorker.ReportProgress(progress);
}
};
bgWorker.RunWorkerCompleted += (s, e) =>
{
//Finish up things
};
bgWorker.RunWorkerAsync();
答案 1 :(得分:1)
不,不是。主要问题是你的进度条 - 它在后台工作线程而不是UI线程上受到欢迎。它也永远不会挂在任何东西上 - 它在哪里显示?
正确的方法是拥有一个包含进度条的表单,并在UI线程中打开它(或者只是开始拍摄它)在启动后台工作程序之前,然后在完成后隐藏它。
Dispatcher的更新逻辑是&#34;正确&#34;虽然它目前触及一个未正确初始化的进度条。但是调用是你必须要做的。