使用ProgressBar作为等待栏 - 如何避免冻结?

时间:2010-07-19 14:53:53

标签: winforms multithreading progress-bar backgroundworker

我正在创建一个自定义图表控件,我希望有可能在其他命令运行时显示某种等待条(即正在创建图表)。

我正在使用ProgressBar(在选框模式下为System.Windows.Forms.ProgressBar)作为此控件的一部分。我不需要更新进度条的状态,我只是想让它一遍又一遍地移动直到创建图表。

现在我在以下方案中使用它:
- 开始等待栏(ProgressBar出现并开始运行)
- 呼叫图表方法
- 图表准备就绪后,等待栏将被隐藏。

问题是:有些图表方法实际上是计算要求,等待栏会在这样的时刻冻结。我该如何避免这些冻结?我应该使用某种线程/后台工作者吗?如果是,那么最简单的方法是什么?

请注意,在准备图表时,我不需要更改进度条的状态。我只需要等待栏启动,在所有计算过程中运行并在此之后停止。

修改

好的,正如所建议的那样,我为这些要求严格的计算创建了一个单独的线程,以避免冻结。

但是如何等待线程完成并且不冻结GUI?

我按照建议here尝试了类似的东西:

Thread t = new Thread( () => { DoSomeLongAndDemandingTask(withParameters); });
t.Start();
t.Join()

// do something that needs to be done after thread finishes
InvokeMeAfterThreadFinished();

但它冻结了GUI。有没有其他办法可以避免这些冻结?

2 个答案:

答案 0 :(得分:4)

您已经回答了自己的问题 - 通常答案是将计算移到后台线程上。有一个名为BackgroundWorker的WinForms组件,为您做了很多工作:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx http://dotnetperls.com/backgroundworker

请注意,您将无法从后台线程访问UI组件,您需要Control.Invoke到UI线程才能访问UI控件。在网上对此进行了大量讨论(并提供了解决方案),因此谷歌搜索将非常容易。

或者,有时后台线程不可行(不确定原因),因此您可以使用Application.DoEvents() - 如果内存服务,则处理消息队列上的待处理消息(包括控制绘制,UI更新)。如果你只做一些导致抖动的工作,这可能是一个更快更简单的选择 - 虽然不经常建议。

答案 1 :(得分:1)

使用BackgroundWorker类是执行后台计算的最简单方法。

但是,请注意,您在后台运行的图表方法不会更新UI。 UI本身的所有更新必须由UI线程执行。因此,后台线程需要“调整”对UI的此类调用 - 请参阅Control.Invoke作为起点。