20

I'm practising on threading and came across this problem. The situation is like this:

  1. I have 4 progress bars on a single form, one for downloading a file, one for showing the page loading status etc...

  2. I have to control the progress of each ProgressBar from a separate thread.

The problem is I'm getting an InvalidOperationException which says

Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on.

Am I wrong in this approach or can anybody tell me how to implement this?

alex
  • 3,710
  • 32
  • 44
Chandra Eskay
  • 2,163
  • 9
  • 38
  • 58
  • 2
    Check out [this](http://www.yoda.arachsys.com/csharp/threads/winforms.shtml) article by Jon Skeet on threading in Windows Forms. It should clear things up. The short explanation would be that you need to invoke the UI elements from your other threads, since the UI runs on its own thread. – alex Sep 30 '11 at 11:46

5 Answers5

59

A Control can only be accessed within the thread that created it - the UI thread.

You would have to do something like:

Invoke(new Action(() =>
{
    progressBar1.Value = newValue;
}));

The invoke method then executes the given delegate, on the UI thread.

ebb
  • 9,297
  • 18
  • 72
  • 123
17

You can check the Control.InvokeRequired flag and then use the Control.Invoke method if necessary. Control.Invoke takes a delegate so you can use the built-in Action<T>.

public void UpdateProgress(int percentComplete)
{
   if (!InvokeRequired)
   {
      ProgressBar.Value = percentComplete;
   }
   else
   {
      Invoke(new Action<int>(UpdateProgress), percentComplete);
   }
}
Peter Kelly
  • 14,253
  • 6
  • 54
  • 63
12

The UI elements can only be accessed by the UI thread. WinForms and WPF/Silverlight doesn't allow access to controls from multiple threads.

A work-around to this limitation can be found here.

Community
  • 1
  • 1
Dennis Traub
  • 50,557
  • 7
  • 93
  • 108
11
 private void Form1_Load(object sender, EventArgs e)
    {
        CheckForIllegalCrossThreadCalls = false;
    }

Maybe this will work.

Rovo93
  • 187
  • 1
  • 4
  • 6
    This will stop the error from showing up, but it doesn't actually fix the issue. There are other, much better answers already in this thread that actually solve the issue and help promote better understanding of why it happened in the first place. – Taegost Jan 28 '19 at 14:17
  • I also like to live dangerously, and this worked for me for my one use case. Thank you. – caliche2000 May 04 '21 at 02:03
2

You need to call method Invoke from non-UI threads to perform some actions on form and other controls.

Tadeusz
  • 6,453
  • 9
  • 40
  • 58