473,402 Members | 2,046 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,402 software developers and data experts.

Using toolStripProgressBar1 inside a Thread

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

this is my code:
Expand|Select|Wrap|Line Numbers
  1. ParameterizedThreadStart Proceso = new ParameterizedThreadStart(this.ReadNPI);
  2.             start2 = new Thread(Proceso);
  3.             start2.IsBackground = true;
  4.             start2.Priority = ThreadPriority.Highest;            
  5.             start2.Start(FilePath2);    
  6.  
Expand|Select|Wrap|Line Numbers
  1.  private void ReadNPI(object FilePath)
  2.         {            
  3.             string FILE = (string)FilePath;
  4.             string connectionString = cnSelected;
  5.             DataSet dataSet1 = new DataSet();
  6.             try
  7.             {
  8.                 string selectString = "SELECT * FROM [" + sheet + "$]";
  9.                 OleDbConnection con = new OleDbConnection(connectionString);
  10.                 OleDbCommand cmd = new OleDbCommand(selectString, con);
  11.                 con.Open();
  12.                 OleDbDataReader theData = cmd.ExecuteReader();
  13.                 List<string> al = new List<string>();
  14.                 int c = theData.FieldCount; 
  15.                 while (theData.Read())
  16.                 {   
  17.                     string NPI = theData.GetValue(0).ToString();
  18.                     al.Add(NPI);             //al es un ArrayList Publico.);
  19.                 }
  20.                 int count = al.Count;
  21.                 this.toolStripProgressBar1.Minimum = 0;
  22.                 this.toolStripProgressBar1.Maximum = count; // The error is HERE
  23.                 this.toolStripProgressBar1.Step = 1;
  24.                 con.Close();                
  25.                 try
  26.                 {
  27.  
  28.                     string filepath = (string)FilePath;  // FilePath es el archivo de NPPES.
  29.                 Begin:
  30.                     StreamReader sr = new StreamReader(filepath);
  31.                     while (sr.Peek() != -1)
  32.                     {
  33.                     Back:
  34.                         string line = sr.ReadLine();
  35.                         string skip = line.Substring(1, 3);
  36.                         if (skip == "NPI")
  37.                         {
  38.                             goto Back;
  39.                         }
  40.                         string[] fields = Regex.Split(line, "\",\"");
  41.                         string NPI = fields.GetValue(0).ToString().Trim().Replace("\"", "");
  42.                         if (al.Contains(NPI))
  43.                         {
  44.                             InsertData(fields);
  45.                             al.Remove(NPI);
  46.                             sr.Close();
  47.                             sr.Dispose();
  48.                             this.toolStripProgressBar1.PerformStep();
  49.                             if (al.Count == 0)
  50.                             {
  51.                                 toolStripStopThread.Visible = false;
  52.                                 TerminateThreads();
  53.                                 break;
  54.                             }
  55.                             goto Begin;
  56.                         }
  57.                     }
  58.                 }
  59.                 catch (Exception ex)
  60.                 {
  61.                     MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
  62.                     TerminateThreads();
  63.                     return;
  64.                 }            
  65.  
  66.             }
  67.             catch (Exception ex)
  68.             {
  69.                 MessageBox.Show(ex.Message);
  70.                 TerminateThreads();
  71.                 return;
  72.             }       
  73.         }
May 26 '10 #1

✓ answered by Christian Binder

You have to use Form's Invoke()-method, this would marshal your operation to the GUI-thread. Because it's not allowed, to do something in your GUI from another thread, which the GUI (Control-object) was created.

You have to do this everytime you set a control's property or call it's method.

E.g. instead of
Expand|Select|Wrap|Line Numbers
  1. this.toolStripProgressBar1.Minimum = 0;
  2. this.toolStripProgressBar1.Maximum = count;
  3. this.toolStripProgressBar1.Step = 1;
you'd better use (if your'e using .net 3.5)

Expand|Select|Wrap|Line Numbers
  1. this.Invoke(new Action(() => {
  2.   this.toolStripProgressBar1.Minimum = 0;
  3.   this.toolStripProgressBar1.Maximum = count;
  4.   this.toolStripProgressBar1.Step = 1;
  5. }
  6.  
Invoke() is a synchronous (blocking) call, if you want to do a non-blocking call, you could use Control's BeginInvoke()-method (has the same signature as Invoke() )

6 6481
tlhintoq
3,525 Expert 2GB
Original Poster: I have xxx, then do yyy then zzz happens. Here's my code ...
Ok. You know what you have.
What you don't have is a question. Nobody here knows why you posted this since you haven't asked anything. You could be asking "What does the error mean?", you could be asking "Which control is it talking about?", you could be asking "Will someone do my debugging for me?"

I recommend you read the FAQ about How to ask a good question so the volunteers will be able to help you.

Commonly this comes from creating a new thread, that then tries to make a change to control on form that was made from the primary thread of the application. For example, your main form has a label or textbox (or progressbar in your case) where you are putting up status updates... and your worker thread is trying to directly write those updates directly to the control. You can't do that. You would need the worker thread to raise an event that your other thread would subscribe to, then react to.

This might help. Two forms, two classes, two threads... its all basically the same thing.

Original Poster: How do I get my Form2 to react to something on my Form1?
How do I make my Form1 control something on my Form2?
Although you can have Form1 directly access items on Form2 it isn't the recommended way to go. It ties the two forms tightly to each other. If a change is made in Form2 such as removing one of the controls, then code in Form1 breaks.
It is better to Form1 raise an event, and have Form2 contain its own code for how to react to this. This places responsibility for Form2 within Form2, and Form1 within Form1.
It keeps Form1 blissfully ignorant of Form2 - and a logging component - and a progress component, and a dozen other little black boxes that can be subscribed to events in Form1, all without Form1 being made responsible for directly affecting controls other than itself.
Events tutorial (including Form to Form which is the same as class to class)
This tutorial for a cash register does exactly that: It makes a virtual numeric keyboard.

Bad: Directly accessing controls of one class/form from another.
Expand|Select|Wrap|Line Numbers
  1. bool IsOn = Form2.button1.IsChecked;
Good: Use a property to get such information
Expand|Select|Wrap|Line Numbers
  1. //Form1
  2. bool IsOn = Form2.IsOn;
Expand|Select|Wrap|Line Numbers
  1. //Form 2
  2. public bool IsOn
  3. {
  4.    get { return CheckBox1.Checked; }
  5.    set { CheckBox1.Checked = value; }
  6. }
It's a subtle but important difference as your applications become more complex. Using properties means your target class/form (Form2) can be changed and updated a thousand different ways yet won't negatively impact the classes that are reading from it. If you change the name of a control for example: It won't break references in all your other classes. If your target form evolves where it needs to do 10 things when it is turned on, then the responsibility stays within Form2, and that burden is not put on Form1 and a dozen other forms that might be using Form2. The goal is to compartimentalize the work so that Form2 is responsiblity SOLELY for Form2. From1 should only have to say "Turn on" or "Turn Off"

Form2
Expand|Select|Wrap|Line Numbers
  1. public bool IsOn
  2. {
  3.    get { return btnMeaningfulName.Checked; }
  4.    set {
  5.             btnMeaningfulName.Checked = value;
  6.             panelDashboard.Visible = value;
  7.             labelStatus = value == true ? "On" : "Off";
  8.             btnRunNow.Enabled = value;
  9.        }
  10. }
Now when Form1 tells Form2 to turn on, Form2 will check a box, make an entire panel visible, change its Status label to say 'On' and enable a Run Now button.
May 26 '10 #2
My question is;
How use toolStripProgressBar1 inside a Thread?
Because I recive the following error in this line:
Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.

Expand|Select|Wrap|Line Numbers
  1.  this.toolStripProgressBar1.Maximum = count;
Starting the Thread:
Expand|Select|Wrap|Line Numbers
  1. ParameterizedThreadStart Proceso = new ParameterizedThreadStart(this.ReadNPI);
  2.             start2 = new Thread(Proceso);
  3.             start2.IsBackground = true;
  4.             start2.Priority = ThreadPriority.Highest;            
  5.             start2.Start(FilePath2);    
Expand|Select|Wrap|Line Numbers
  1.  private void ReadNPI(object FilePath)
  2.         {            
  3.             string FILE = (string)FilePath;
  4.             string connectionString = cnSelected;
  5.             DataSet dataSet1 = new DataSet();
  6.             try
  7.             {
  8.                 string selectString = "SELECT * FROM [" + sheet + "$]";
  9.                 OleDbConnection con = new OleDbConnection(connectionString);
  10.                 OleDbCommand cmd = new OleDbCommand(selectString, con);
  11.                 con.Open();
  12.                 OleDbDataReader theData = cmd.ExecuteReader();
  13.                 List<string> al = new List<string>();
  14.                 int c = theData.FieldCount; 
  15.                 while (theData.Read())
  16.                 {   
  17.                     string NPI = theData.GetValue(0).ToString();
  18.                     al.Add(NPI);             //al es un ArrayList Publico.);
  19.                 }
  20.                 int count = al.Count;
  21.                 this.toolStripProgressBar1.Minimum = 0;
  22.                 this.toolStripProgressBar1.Maximum = count;
  23.                 this.toolStripProgressBar1.Step = 1;
  24.                 con.Close();               
  25.                  try
  26.                 {
  27.  
  28.                     string filepath = (string)FilePath;  // FilePath es el archivo de NPPES.
  29.                 Begin:
  30.                     StreamReader sr = new StreamReader(filepath);
  31.                     while (sr.Peek() != -1)
  32.                     {
  33.                     Back:
  34.                         string line = sr.ReadLine();
  35.                         string skip = line.Substring(1, 3);
  36.                         if (skip == "NPI")
  37.                         {
  38.                             goto Back;
  39.                         }
  40.                         string[] fields = Regex.Split(line, "\",\"");
  41.                         string NPI = fields.GetValue(0).ToString().Trim().Replace("\"", "");
  42.                         if (al.Contains(NPI))
  43.                         {
  44.                             InsertData(fields);
  45.                             al.Remove(NPI);
  46.                             sr.Close();
  47.                             sr.Dispose();
  48.                             this.toolStripProgressBar1.PerformStep();
  49.                             if (al.Count == 0)
  50.                             {
  51.                                 toolStripStopThread.Visible = false;
  52.                                 TerminateThreads();
  53.                                 break;
  54.                             }
  55.                             goto Begin;
  56.                         }
  57.                     }
  58.                 }
  59.                 catch (Exception ex)
  60.                 {
  61.                     MessageBox.Show(ex.Message, "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
  62.                     TerminateThreads();
  63.                     return;
  64.                 }            
  65.  
  66.             }
  67.             catch (Exception ex)
  68.             {
  69.                 MessageBox.Show(ex.Message);
  70.                 TerminateThreads();
  71.                 return;
  72.             }       
  73.         }
May 26 '10 #3
tlhintoq
3,525 Expert 2GB
Gabiel: How use toolStripProgressBar1 inside a Thread?
If the toolStripProgressBar was made from a different thread (the main thread that made the form) then you don't. That's what the error message is telling you. One thread does not have the ability to affect controls made from a different thread. Your progressbar was made by the thread that build the form. Your ReadNPI method is happening on a different thread.

Your ReadNPI thread Processo needs to raise an event, and your main GUI thread needs to react to that event.
May 26 '10 #4
Christian Binder
218 Expert 100+
You have to use Form's Invoke()-method, this would marshal your operation to the GUI-thread. Because it's not allowed, to do something in your GUI from another thread, which the GUI (Control-object) was created.

You have to do this everytime you set a control's property or call it's method.

E.g. instead of
Expand|Select|Wrap|Line Numbers
  1. this.toolStripProgressBar1.Minimum = 0;
  2. this.toolStripProgressBar1.Maximum = count;
  3. this.toolStripProgressBar1.Step = 1;
you'd better use (if your'e using .net 3.5)

Expand|Select|Wrap|Line Numbers
  1. this.Invoke(new Action(() => {
  2.   this.toolStripProgressBar1.Minimum = 0;
  3.   this.toolStripProgressBar1.Maximum = count;
  4.   this.toolStripProgressBar1.Step = 1;
  5. }
  6.  
Invoke() is a synchronous (blocking) call, if you want to do a non-blocking call, you could use Control's BeginInvoke()-method (has the same signature as Invoke() )
May 26 '10 #5
tlhintoq
3,525 Expert 2GB
Yeah, you can use invoke... but I would avoid it. It tightly ties your thread/class to the GUI. If you change the GUI then you break the other threads. It really violates the whole idea that each part of your application should be a self-contained little black box that does its own job and nobody else's.

If you have your thread raise an event... You could have 10 different classes subscribe to it. Or none. One could update the progress bar, one could add a log entry, one could add the file to a processing queue, one could open another form asking for feedback on how the user liked the system....

The thread should only be responsible for what the thread does - not the GUI user experience.
May 26 '10 #6
Christian Binder
218 Expert 100+
@tlhintoq
Yes, it's true, the Thread's operations shouldn't be responsible for how the GUI should handle this.
But in the source-code the Thread is private within the Form, so there won't be problems in case of code reusage or anything else.
If the threaded operation would be done outside (other class than) the form-class, it wouldn't be nice to do this Invoke.

But at least you'd nee to do invocation anyway, because if you'd use an event in the Tread, your event-handler would be called from the Thread's context and invocation will be necessary to do GUI things.
Now there are different approaches, how to handle it, the simplest would be
(it's conceptual, I don't know, if it's working that way)
Expand|Select|Wrap|Line Numbers
  1. private void Thread_Ready(object sender, EventArgs e) {
  2.   if(InvokeRequired)
  3.     Invoke(new Action(DoSomething));
  4.   else
  5.     DoSomething()
  6. }
  7.  
  8. private void DoSomething() { ... }
  9.  
the other approach would be marshalling in your threaded context
e.g.
Expand|Select|Wrap|Line Numbers
  1. class MyThreadedOperation {
  2.   List<KeyValuePair<Action, SynchronizationContext>> _callbacks = new List...();
  3.  
  4.   public event Action OnReady {
  5.     add {
  6.       _callbacks.Add(new KeyValuePair(value, SynchronizationContext.Current ?? new SynchronizationContext());
  7.     }
  8.  
  9.     remove {
  10.       _callbacks.Remove(value); //do check if list contains before ...
  11.     }
  12.   }
  13.  
  14.   public void DoSomethingThreaded() {
  15.     new Thread(...(DoSomething)).Start();
  16.   }
  17.  
  18.   private void DoSomething() {
  19.     // do some heavy operations
  20.  
  21.     // callback listeners
  22.     foreach(KeyValuePair<Action, SynchronizationContext> kvp in _callbacks) {
  23.       kvp.Value.Post(new SendOrPostCallback(foo => kvp.Key()), null);
  24.       // Post-method is async like BeginInvoke()
  25.       // Send-methood would be synchronous like Invoke()
  26.     }
  27.   }
  28. }
  29.  
May 27 '10 #7

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: przemas_r | last post by:
Hello everybody. I've found python's behaviour I can't understand. Namely the way os.system () works depending if it's being run in Thread's run function or run in 'normal' way. >>> os.system...
28
by: Daniel | last post by:
Hello =) I have an object which contains a method that should execute every x ms. I can use setInterval inside the object construct like this - self.setInterval('ObjectName.methodName()',...
4
by: Coot | last post by:
I've been running many tests of the Asynchronous Delegate technique and I find that although BeginInvoke() does queue the method delegate onto a worker thread, it always does so on the _same_...
0
by: Art Guerra | last post by:
Any tips or information would be most appreciated! Here is my scenario simplified: I have a main application form (Form1) and on that form is a listView control. On a separate form (Form2), the...
8
by: NG | last post by:
Hi All I am using interop blocking COM call from within a worker thread. This is a part of Windows Application. I find that if I remove the blocking COM call and instead use an infinite while...
9
by: Hasani \(remove nospam from address\) | last post by:
I have a website with 2 aspx pages Foo.aspx, and bar.aspx The content of both files is //in 1 file Hello <%=Session.ToString()%> ================
1
by: Joel Byrd | last post by:
I've been using an eval() statement, which has been working fine until I put it inside of a function. Is this a known problem, and is there a known solution/work-around to this?
1
by: Max Evans | last post by:
I have a XML file, which contains itemid-elements, e.g.: <itemid>3</itemid> <itemid>12</itemid> Now I want to convert these IDs to the corresponding name via XSLT. I thought I could do it this...
0
by: jonpc2001 | last post by:
I'm trying to workout if it is possible to startup a windows form application and create multiple tab pages (with various controls) using a different thread from the main one. The reason why I...
5
by: sgurukrupagmailcom | last post by:
Hi, I haven't come accross an elegant solution to a design problem that I show below. Have a look at the piece of code here: class Exc { Exc () { System.out.println ("Haribol"); }
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.