Friday, May 28, 2010

C#: Cross-thread operation not valid: Control ‘progressBar1’ accessed from a thread other than the thread it was created on

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

This goes for any control that needs to be touched by a worker thread, you cannot do it directly.  You must do a callback so the main UI thread actually does the update.

Reproduce the problem:

        private void button1_Click(object sender, EventArgs e)
        {
            progressBar1.Minimum = 0;
            progressBar1.Maximum = 100;

            System.Threading.Thread worker = new System.Threading.Thread(doWork);
            worker.Start();
        }

        private void doWork()
        {
            for (int i = 0; i < progressBar1.Maximum; i++)
            {
                progressBar1.PerformStep();
            }
        }

Solution is:
Add this method, and instead of calling progressBar1.PerformStep(), call ActuallyPerformStep():
        delegate void CallPerformStep(ProgressBar myProgressBar);
        private void ActuallyPerformStep(ProgressBar myProgressBar)
        {
            if (myProgressBar.InvokeRequired)
            {
                CallPerformStep del = ActuallyPerformStep;
                myProgressBar.Invoke(del, new object[] { myProgressBar });
                return;
            }

            myProgressBar.PerformStep();
        }

And now the main UI thread is calling the UI Control.

11 comments:

  1. I have an error for this code...
    The error is,

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


    public void train_network()
    {
    int set_number;
    float average_error=0.0F;
    progressBar1.Maximum =epochs;
    for(int epoch=0;epoch<=epochs;epoch++)
    {
    average_error=0.0F;
    for(int i=0;i<number_of_input_sets;i++)
    {
    set_number=rnd.Next(0,number_of_input_sets);
    get_inputs(set_number);
    get_desired_outputs(set_number);
    calculate_outputs();
    calculate_errors();
    calculate_weights();
    average_error=average_error+get_average_error();
    }

    progressBar1.PerformStep();
    label15.Text =epoch.ToString ();
    label15.Update ();
    average_error=average_error/number_of_input_sets;
    if(average_error<error_threshold)
    {
    epoch=epochs+1;
    progressBar1.Value =progressBar1.Maximum;
    label22.Text ="<"+error_threshold.ToString ();
    label22.Update ();
    }
    }
    label27.Text ="Ready";
    label27.Update ();
    }
    ...............................................
    Plz,clear the error.. help me.. thanks..

    ReplyDelete
  2. Anyone help me the above post...
    plz...
    Thank u..

    ReplyDelete
    Replies
    1. Coding Cramp Dan here! In this method, begin with:
      public void train_network()
      {
      if (progressBar1.InvokeRequired)
      {
      CallPerformStep del = train_network;
      progressBar1.Invoke(del, new object[] { progressBar1});
      return;
      }

      //then continue with your normal method content:
      int set_number;
      float average_error=0.0F; ....

      Delete
    2. Thank u...
      I have an error for,

      The type or namespace name 'CallPerformStep' could not be found (are you missing a using directive or an assembly reference?)

      which reference i have to add in my project..

      Delete
    3. Oh, I'm sorry, I forgot the delegate in the code I pasted to you. Put this above your method:
      delegate void CallPerformStep(ProgressBar progressBar1);

      Delete
    4. Thank u..
      I have arrange my code like this,


      delegate void CallPerformStep(ProgressBar progressBar1);
      public void train_network()
      {
      if (progressBar1.InvokeRequired)
      {
      CallPerformStep del = train_network;
      progressBar1.Invoke(del, new object[] { progressBar1});
      return;
      }

      int set_number;
      float average_error=0.0F;
      progressBar1.Maximum =epochs;
      for(int epoch=0;epoch<=epochs;epoch++)
      {
      average_error=0.0F;
      for(int i=0;i<number_of_input_sets;i++)
      {
      set_number=rnd.Next(0,number_of_input_sets);
      get_inputs(set_number);
      get_desired_outputs(set_number);
      calculate_outputs();
      calculate_errors();
      calculate_weights();
      average_error=average_error+get_average_error();
      }
      progressBar1.PerformStep();
      label15.Text =epoch.ToString ();
      label15.Update ();
      average_error=average_error/number_of_input_sets;
      if(average_error<error_threshold)
      {
      epoch=epochs+1;
      progressBar1.Value =progressBar1.Maximum;
      label22.Text ="<"+error_threshold.ToString ();
      label22.Update ();
      }
      }
      label27.Text ="Ready";
      label27.Update ();

      }
      -------------------------------------------------
      It shows an error for,
      No overload for 'train_network' matches delegate 'Unicode_OCR.Form1.CallPerformStep'

      Delete
    5. Hey there! This time I put it all in Visual Studio and got it to compile and run:

      delegate void CallPerformStep();
      public void train_network()
      {
      if (progressBar1.InvokeRequired)
      {
      CallPerformStep del = train_network;
      progressBar1.Invoke(del);
      return;
      }

      int set_number;
      float average_error = 0.0F;
      progressBar1.Maximum = epochs;
      for (int epoch = 0; epoch <= epochs; epoch++)
      {
      average_error = 0.0F;
      for (int i = 0; i < number_of_input_sets; i++)
      {
      set_number = rnd.Next(0, number_of_input_sets);
      get_inputs(set_number);
      get_desired_outputs(set_number);
      calculate_outputs();
      calculate_errors();
      calculate_weights();
      average_error = average_error + get_average_error();
      }
      progressBar1.PerformStep();
      label15.Text = epoch.ToString();
      label15.Update();
      average_error = average_error / number_of_input_sets;
      if (average_error < error_threshold)
      {
      epoch = epochs + 1;
      progressBar1.Value = progressBar1.Maximum;
      label22.Text = "<" + error_threshold.ToString();
      label22.Update();
      }
      }
      label27.Text = "Ready";
      label27.Update();
      }

      Delete
    6. It works well..Thank u so much....

      Delete
  3. I want solution for the above Error, plz give solution as soon as possible..
    Thank u..

    ReplyDelete
  4. Plz, help me...

    I want some quick solution for the above post plz..

    ReplyDelete
  5. Good response, it works. But can any one give hint for Ethiopic Ge'ez how i can develop OCR? if you have any knowledge please sent to my address haliemit@gmail.com

    ReplyDelete