2009-05-29 47 views
2

我在主线程和另一个线程做了一些计算。我想从另一个线程中正在完成的工作中更新表单上的状态栏。什么是最好的方法来做到这一点?从另一个线程更新进度栏

到目前为止,我所试过的一切都让事情真的很慢。我使用Visual Studio 2005

+0

你必须要更加具体 - 什么是慢?你如何使用线程? – 2009-05-29 02:25:07

回答

2

确保您只能从主线程更新用户界面,否则你就会有问题。您可以通过调用Invoke来切换线程上下文。这里有一个很好的帖子here

1

你可以发送消息到主线程,并得到它的更新进度条,虽然你那么需要检查的消息。您也可以执行与轮询功能相同的操作。

1

您可以使用编组技术(如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和工作线程上获得更高的吞吐量。
  • BeginInvoke一样,没有使UI消息队列饱和的机会。
  • 每次您需要从工作线程更新UI时,您不必乱抛垃圾代码与Invoke调用。