Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
665 views
in Technique[技术] by (71.8m points)

winforms - Updating a Progress Bar from Another Thread

I have a windows form on the main thread and another thread that does some calculations. I'd like to update the status bar on my form from the work being done in the other thread. What's the best way to do this?

So far everything I've tried just makes things run really slowly. I'm using Visual Studio 2005.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use the marshaling techniques like Control.Invoke to execute a delegate on the UI thread where UI elements can be safely manipulated, but that approach is not very good. Actually, it is a terrible approach if all you want to do is update simple progress information.

By far the best method for doing this is:

  • Have your worker thread publish progress information to a shared variable.
  • Have your UI thread poll for it via a System.Windows.Forms.Timers on an interval that works well for you.

Here is what it might look like.

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;
  }
}

This works well because:

  • The percentComplete field is declared 'volatile' ensuring its value can be reliably read from multiple threads.
  • The UI thread gets to dictate when and how often the UI gets updated...the way it should be!
  • The worker thread does not have to wait for a response from the UI thread before it can proceed as would be the case with Invoke.
  • It breaks the tight coupling between the UI and worker threads that Invoke would impose.
  • It is more efficient...considerably.
  • You get more throughput on both the UI and worker threads.
  • There is no chance of saturating the UI message queue as could be the case with BeginInvoke.
  • You do not have to litter you code with Invoke calls everytime you need to update the UI from the worker thread.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...