进度条&后台工作者

时间:2017-07-13 06:59:36

标签: c# wpf multithreading

我尝试使用进度条在应用程序的初始屏幕上显示。

虽然我很惊讶它只是通过致电progressBar.Value = newValue而无法工作......

所以我做了一些研究,发现其他繁重的工作可能会阻止UI线程......

Q1

但我真正理解的是,如果UI线程上发生了所有事情,为什么进度条没有刷新

即使我正在做大量工作"像I / O一样,在完成I / O时,我刷新进度条......所以在开始另一个I / O之前不应该刷新进度条???

Q2

好吧,现在让我说我必须使用后台工作人员来完成繁重的工作和UI线程来刷新进度条。

我所做的繁重工作是加载应用程序。它准备了稍后我将需要的对象,在繁重的工作之后,我需要用新的窗口等启动应用程序。

我什么时候做?

我是否添加了RunWorkerCompleted事件处理程序并将应用程序剩余代码的每一部分都放在其中?

然后,事件处理程序中发生的一切,都是UI线程或后台工作者的另一个线程???

非常感谢你的帮助

据我所知,这是我的代码的一部分:

相关进度条:

<ProgressBar Name="progressBar" Height="20" Value="0" Maximum="100" Minimum="0" />

工人:

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += WorkerOnDoWork;
worker.RunWorkerCompleted += WorkerOnRunWorkerCompleted;
worker.ProgressChanged += SplashManager.onProgress;
worker.RunWorkerAsync();

SplashManager.onProgress方法:

public static void onProgress(object sender, EventArgs e)
{
    screen.setProgress(((ProgressChangedEventArgs)e).ProgressPercentage);
}

屏幕setProgress方法:

public void setProgress(double progress)
{
    progressBar.Value = progress;
}

现在我在progressBar.Value = progress:

上有例外

调用线程无法访问此对象,因为另一个线程拥有它

2 个答案:

答案 0 :(得分:2)

进度条控件将在获取重绘消息时刷新。但是,当您的慢速方法正在运行时,不会处理消息。

您可以在更改Application.DoEvents()后调用progressBar.Value,这将处理所有等待的消息(在极端情况下可能包括点击按钮或关闭您正在使用的表单)。

或致电(也在更改价值后):

progressBar.Invalidate();
progressBar.Update();

答案 1 :(得分:0)

你可以像Mykola Kovalchuk建议的那样做。但是对于繁重的工作,建议使用 BackgroundWorker ,因为它支持取消,您可以在线程处于活动状态时与UI进行交互,例如单击取消按钮。 / p>

Q2:

  

我什么时候做?

     

我是否添加了RunWorkerCompleted事件处理程序并将应用程序剩余代码的每一部分都放在其中?

是的,您可以在 BackgroundWorker 忙碌时执行其他有用的工作,并且当RunWorkerCompleted触发时,您可以调用函数来执行您想要的操作。

  

然后,事件处理程序中发生的一切,都是UI线程或后台工作者的另一个线程???

它确实在主UI线程上运行。更多信息请MSDN

使用 BackgroundWorker 时,您可以使用 ProgressChanged 事件更新进度条。