Windows Develop Bookmark and Share   
 index > Windows Forms General > Q: Cross-Thread Operations...
 

Q: Cross-Thread Operations...

Hello everybody. I have a question.

Assume I have the following form

http://img145.imageshack.us/img145/5121/screenshotic0.jpg

I also have a public class looking like this:

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;

using System.IO;

namespace ThreadSafeProgressBar

{

public class myClass

{

ProgressBar m_pb;

Label m_lbl;

public myClass(ProgressBar pb,Label lbl)

{

m_pb = pb;

m_lbl = lbl;

}

public void Work(object state)

{

int max = 10000;

m_pb.Maximum = max;

for(int i = 0 ; i <= max ; i++)

{

m_pb.Value = i;

m_lbl.Text = i.ToString();

}

}

}

}

After pressing the button on the main form I do the following actions

private void button1_Click(object sender, EventArgs e)

{

myClass o_myClass = new myClass(progressBar1,label1);

ThreadPool.QueueUserWorkItem(new WaitCallback(o_myClass.Work));

}

NB:progressBar1 and label1 are the way I have named my controls on the main form

After starting the program I get the following error:

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

Is there a way to fix this? How can I access progressBar1 from another class started in ThreadPool...Any ideas would be greatly appreciated!

kirchu

kirchu  Tuesday, January 16, 2007 2:09 PM

In short it is illegal in the Windows world for a (background) thread to control resources that it does not own/did not create. Sure, like speeding it’s not always caught or enforced, but when it is it is harsh.

The way to get around such an issue in this case is have the update to the progress bar occur in the context of it’s owning thread and you can manually detect if this is necessary by calling the InvokeRequired property of the progress bar to determine if a call to Invoke() is required.... this is however a little cumbersome so instead I’d suggest taking a look at BackgroundWorker.

With BackgroundWorker you’ve got a class that offers functionality similar to the ThreadPool only does the work behind the scenes so that if wired up properly, is thread safe.

Try this example based on your own:

           BackgroundWorker bgw;

...          

           m_pb.Maximum = 10000;

           bgw = new BackgroundWorker();
          
           bgw.WorkerReportsProgress = true;

           //Method to be called when worker is run
           bgw.DoWork+=new DoWorkEventHandler(bgw_DoWork);

           //Event handler called when progress is reported
           bgw.ProgressChanged+=new ProgressChangedEventHandler(bgw_ProgressChanged);

           //Run BackgroundWorker
           bgw.RunWorkerAsync(m_pb.Maximum);

...

        void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
           int i = (int)e.UserState;

           m_pb.Value = i;
           m_lbl.Text = i.ToString();
        }

       void bgw_DoWork(object sender, DoWorkEventArgs e)
       {
          int max = (int)e.Argument;

          for (int i = 0; i <= max; i++)
          {
             bgw.ReportProgress(0, i);
          }
       }

Brendan Grant  Tuesday, January 16, 2007 2:44 PM

You can use google to search for other answers

Custom Search

More Threads

• Flicker-free transparent panel?
• Windows Forms application setting automatic program run on boot up.
• How do you get the Form parenting the control?
• Adding a ComboBox type filters to DataGridView
• Cannot inherit from ToolStripControlHost
• Keyevent F5
• Need Help with Relating Data
• DropDown with colors
• Access Main Form Variables From Child
• ToolStripMenuItem DropDown painting