views:

1609

answers:

4

I've done some research and I can't really find a preferred way to do updating of form controls from a worker thread in C#. I know about the BackgroundWorker component, but what is the best way to do it without using the BackgroundWorker component?

+3  A: 

Why dont you want to do it using the BackgroundWorker? It has a fantastic callback event called ProgressChanged which lets the UI thread know about updates, perfect for progess bar-type updates and the like.

link to details

Mark
+1  A: 

There's a discussion related to this here and one here.

Essentially, you use Invoke to accomplish it.

Best of luck!

itsmatt
+6  A: 

There's a general rule of thumb that says don't update the UI from any thread other than the UI thread itself. Using the features of the BackgroundWorker is a good idea, but you don't want to and something is happening on a different thread, you should do an "Invoke" or BeginInvoke to force the delegate to execute the method on the UI thread.

Edit: Jon B made this good point in the comments:

Keep in mind that Invoke() is synchronous and BeginInvoke() is asynchronous. If you use Invoke(), you have to be careful not to cause a deadlock. I would recommend BeginInvoke() unless you really need the call to be synchronous.

Some simple example code:

// Updates the textbox text.
private void UpdateText(string text)
{
  // Set the textbox text.
  m_TextBox.Text = text;
}

public delegate void UpdateTextCallback(string text);

// Then from your thread you can call this...
m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText),
    new object[]{"Text generated on non-UI thread."});

The code above is from a FAQ about it here and a longer more involved one here.

AR
What exactly does the m_TextBox.Invoke do? Does it force the delegate to be executed on the UI thread?
Yttrium
Exactly. Keep in mind that Invoke() is synchronous and BeginInvoke() is asynchronous. If you use Invoke(), you have to be careful not to cause a deadlock. I would recommend BeginInvoke() unless you really need the call to be synchronous.
Jon B
Good call, Jon B. I should have mentioned that. I'll edit to reflect the point.
AR
So what is the benefit of using this method as opposed to a BackgroundWorker?
Mark
I wouldn't say that there was necessarily a benefit to using this approach over the BackgroundWorker but the question specifically said "...but what is the best way to do it without using the BackgroundWorker component?" :)
AR
I see, I guess I thought maybe there was a known issue that I have not seen using the BackgroundWorker that Yttrium found during his research
Mark
How could the use of Invoke cause a deadlock?
Yttrium
+1  A: 

I would also consider InvokeRequired (VS2008 only) when calling Invoke. There are times that you will not be updating the UI from a seperate thread. It saves the overhead of creating the delegate etc.

if (InvokeRequired)
        {
            //This.Invoke added to circumvent cross threading exceptions.
            this.Invoke(new UpdateProgressBarHandler(UpdateProgressBar), new object[] { progressPercentage });
        }
        else
        {
            UpdateProgressBar(progressPercentage);
        }