从另一个线程更新进度条

时间:2009-05-29 02:09:58

标签: winforms multithreading visual-studio-2005

我在主线程上有一个Windows窗体,另一个线程做了一些计算。我想更新我的表单上的状态栏,从另一个线程中完成的工作。最好的方法是什么?

到目前为止,我尝试的所有事情都让事情变得非常缓慢。我正在使用Visual Studio 2005。

3 个答案:

答案 0 :(得分:3)

您可以使用像Control.Invoke这样的编组技术在UI线程上执行委托,可以安全地操作UI元素,但这种方法不是很好。实际上,如果您只想更新简单的进度信息,这是一种糟糕的方法。

到目前为止,执行此操作的最佳方法是:

  • 让您的工作线程将进度信息发布到共享变量。
  • 让您的UI线程通过System.Windows.Forms.Timers以适合您的时间间隔进行轮询。

这可能是它的样子。

public class Example : Form
{
  private volatile int percentComplete = 0;

  private void StartThreadButton_Click(object sender, EventArgs args)
  {
    StatusBarUpdateTimer.Enabled = true;
    new Thread(
      () =>
      {
        for (int i = 1; i <= 100; i++)
        {
          DoSomeWork();
          percentComplete = i;
        }
      }).Start();
  }

  private void StatusBarUpdateTimer_Tick(object sender, EventArgs args)
  {
    yourStatusBarPanel.Text = percentComplete.ToString() + "%";
    StatusBarUpdateTimer.Enabled = percentComplete < 100;
  }
}

这很有效,因为:

  • UI线程决定了UI的更新时间和频率......应该是这样的!
  • 工作线程不必等待来自UI线程的响应,然后才能继续Invoke的情况。
  • 它打破了Invoke将强加的UI和工作线程之间的紧密耦合。
  • 效率更高......相当。
  • 您可以在UI和工作线程上获得更多吞吐量。
  • BeginInvoke的情况一样,没有可能使UI消息队列饱和。
  • 每次需要从工作线程更新UI时,您都不必使用Invoke调用来编写代码。

答案 1 :(得分:2)

确保只从主线程更新用户界面,否则您将遇到问题。您可以通过调用Invoke来切换线程上下文。有一篇很好的帖子here

答案 2 :(得分:1)

您可以向主线程发送消息并让它更新进度条,但您需要检查消息。你也可以做与投票功能相同的事情。