views:

1655

answers:

4

What is the best way to update a label on a windows forms application while processing.

I have a loop that does some processing to files on the users system when the user clicks a button.

foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
   // Do processing
   // Show progress bar
   // Update Label on Form, "f.Name is done processing, now processing..."
}

Could someone please point me to some sample code. I am new to Windows Forms, my search on google resulted in many different types of articles and I am not sure what exactly this is called. Is it Threading, delegates?

Thanks.

+1  A: 

If your processing is lengthy do it in a backgroundworker thread.

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

devSpeed
+6  A: 

You should be doing this on another thread, and then updating your UI thread from that thread. You are blocking further processing by performing this work on the UI thread.

If you can't move this code to the UI thread, then you could always call DoEvents, but I strongly suggest you explore these options first:

casperOne
I agree with this - especially for BackgroundWorker. I use it frequently myself. BackgroundWorkers make multi-threading operations like this simple and easy!
Keithius
+2  A: 

A quick fix for you would be:

Label1.Text = f.Name + " is done processing, now processing...";
Label1.Refresh();

You really want to avoid DoEvents, otherwise you'll have problems if your user repeatedly presses buttons on your form.

Patrick McDonald
+3  A: 

You'll need to get your data from one thread to the other. This can be done a couple ways...

First, your "background" thread could update some kind of "CurrentStatus" string variable that it changes as it goes along. You could then put a timer on your form that would then grab the CurrentStatus variable and update the label with it.

Second, you could simply invoke the operation from the background thread to the UI thread with a delegate using the InvokeRequired property of the label control. So for example...

private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
    if (this.label1.InvokeRequired)
    {
        this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status });
        return;
    }

    this.label1.Text = status;
}

You can call that UpdateStatus() method from any thread (UI or background) and it will detect whether or not it needs to invoke the operation on the main UI thread (and if so, does it).

Edit: To actually set up the thread, you can do so like this:

    private void StartProcessing()
    {
        System.Threading.Thread procThread = new System.Threading.Thread(this.Process);

        procThread.Start();
    }

    private void Process() // this is the actual method of the thread
    {
        foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
        {
            // Do processing
            // Show progress bar
            // Update Label on Form, "f.Name is done processing, now processing..."
            UpdateStatus("Processing " + f.Name + "...");                
        }
    }

Then when the user clicks the "GO" button you'll simply call StartProcessing().

routeNpingme