代码之家  ›  专栏  ›  技术社区  ›  Gacek

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

  •  1
  • Gacek  · 技术社区  · 16 年前

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

    我在用 ProgressBar ( System.Windows.Forms.ProgressBar 在选框模式下)作为此控件的一部分。我不需要更新进度条的状态,我只希望它在创建图表之前不断地移动。

    现在我将它用于以下方案:
    -启动等待栏( 进度条 出现并开始运行)
    -调用图表方法
    -当图表准备就绪时,等待栏将被隐藏。

    问题是:一些图表方法确实需要计算,等待条在这种时刻冻结。我怎样才能避免这些结冰呢?我应该使用某种线程/后台工作者吗?如果是,那么最简单的方法是什么?

    注意,在准备图表时,我不需要更改进度条的状态。我只需要等待栏来启动、运行所有计算,然后停止。

    编辑

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

    但是如何等待线程完成而不冻结GUI呢?

    我按建议试过了 here ,就像这样:

    Thread t = new Thread( () => { DoSomeLongAndDemandingTask(withParameters); });
    t.Start();
    t.Join()
    
    // do something that needs to be done after thread finishes
    InvokeMeAfterThreadFinished();
    

    但它冻结了图形用户界面。有没有其他方法可以避免这些冻结?

    2 回复  |  直到 16 年前
        1
  •  4
  •   Adam Houldsworth    16 年前

    您已经回答了自己的问题——通常的答案是将计算转移到后台线程上。有一个叫做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更新)。如果你只做了一点会引起抖动的工作,这可能是一个更快更简单的选择——尽管不建议太频繁。

        2
  •  1
  •   Justin Ethier    16 年前

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

    但是,请注意,您在后台运行的图表方法不会更新UI。对UI本身的所有更新都必须由UI线程执行。因此,后台线程将需要“整理”对UI的此类调用-请参见 Control.Invoke 从这一点开始。

    推荐文章