Home > C#, WinForms > WinForms: Show progress on long-running operations

WinForms: Show progress on long-running operations

January 30th, 2012 Leave a comment Go to comments

    When I have a long-running operation to execute I always use the best practice demonstrated here. Keeping the UI responsive to user interaction, I start a lengthy task in a separate thread and then update a ProgressBar control step by step from the executing operation. The progress data is passed to UI thread through the BeginInvoke or Invoke methods of the ProgressBar control or any other UI control, since all UI controls are created in UI thread and must be updated from it. Much time has passed since the time when the article was written. So now we have Anonymous Methods, Actions, Funcs, the upgraded ThreadPool class and so on. Using these innovations I’ve rewritten the approach described by Chris Sells. Look at the code sample below. This code sample simulates a treatment of group of files:

private void startBtn_Click(object sender, EventArgs e)
{
    // the array of file paths
    string[] filePaths = ... 

    UpdateProgressBar(0);            

    // start lengthy task in separate thread
    ThreadPool.QueueUserWorkItem(new WaitCallback(new Action<object>(delegate(object state)
    {                
        DoSomethingWithFiles(filePaths);
    })));
}

private void DoSomethingWithFiles(string[] filePaths)
{
    for (int i = 0; i < filePaths.Length; i++)
    {
        string fileText = File.ReadAllText(filePaths[i]);

        // do something with the read file content
        ...
                
        // set refreshed value to ProgressBar
        UpdateProgressBar((i + 1) * 100 / filePaths.Length);                
    }

    // set refreshed value to ProgressBar
    UpdateProgressBar(100);
}

private void UpdateProgressBar(int currentValue)
{
    // if it's UI thread, simply update ProgressBar as usual. 
    // Otherwise, make the current method be called in UI thread.
    if (progressBar1.InvokeRequired)
        progressBar1.BeginInvoke(new Action(delegate() { UpdateProgressBar(currentValue); }));
    else
        progressBar1.Value = currentValue;
}

It’s assumed that startBtn and progressBar1 are added to the form. When startBtn is clicked, the startBtn_Click method is called and starts the DoSomethingWithFiles long-running operation in separate thread. The DoSomethingWithFiles calls the UpdateProgressBar from time to time to show the current progress. The UpdateProgressBar checks whether it’s called from UI thread. If so, it just updates the ProgressBar, otherwise, initiates its own invoking from the UI thread.

As you can see, the obtained code does the same but is more compact.

Related posts:
 
Categories: C#, WinForms Tags: ,
  1. No comments yet.
  1. No trackbacks yet.