6

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?

Yttrium
  • 2,057
  • 7
  • 25
  • 28

4 Answers4

10

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.
  • 39,615
  • 9
  • 44
  • 52
  • What exactly does the m_TextBox.Invoke do? Does it force the delegate to be executed on the UI thread? – Yttrium Oct 15 '08 at 23:48
  • 4
    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 Oct 15 '08 at 23:53
  • Good call, Jon B. I should have mentioned that. I'll edit to reflect the point. – AR. Oct 16 '08 at 00:04
  • So what is the benefit of using this method as opposed to a BackgroundWorker? – Mark Oct 16 '08 at 00:07
  • 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. Oct 16 '08 at 00:10
  • 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 Oct 16 '08 at 00:19
  • How could the use of Invoke cause a deadlock? – Yttrium Oct 16 '08 at 15:10
5

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
  • 14,820
  • 17
  • 99
  • 159
1

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

Essentially, you use Invoke to accomplish it.

Best of luck!

Community
  • 1
  • 1
itsmatt
  • 31,265
  • 10
  • 100
  • 164
1

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