posts - 78, comments - 79, trackbacks - 84

My Links

News

View Anthony Trudeau's profile on LinkedIn

Add to Technorati Favorites

Article Categories

Archives

Post Categories

Other Links

Difference with Threading

I noticed a difference this weekend with how multi-threading works with the Thread class.  Prior to CLR 2.0 you could perform cross-thread operations.  Now, doing so generates an InvalidOperationException with the message “Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on.”

Here is the code that will compile on both 1.1 and 2.0, but fails on 2.0 with the aforementioned exception:

public class Form1 : System.Windows.Forms.Form
{
     private System.Windows.Forms.ProgressBar progressBar1;
     private System.Windows.Forms.Button startButton;
     private System.Windows.Forms.Button cancelButton;
     private System.ComponentModel.Container components = null;

     private bool m_cancelled = false;

     // designer code removed for brevity   

     private bool Cancelled
     {
          get { return m_cancelled; }
          set { m_cancelled = value; }
     }

     private void startButton_Click(object sender, System.EventArgs e)
     {
          Cancelled = false;
          startButton.Enabled = false;
          cancelButton.Enabled = true;

          Thread processThread = new Thread(new ThreadStart(ProcessSomething));
          processThread.Start();
     }

     private void cancelButton_Click(object sender, System.EventArgs e)
     {
          Cancelled = true;
     }

     private void ProcessSomething()
     {
          DateTime startTime = DateTime.Now;

          do
          {
              if (Cancelled) break;

              TimeSpan duration = DateTime.Now.Subtract(startTime);
              double totalSeconds = duration.TotalSeconds;
              double percent = totalSeconds / 10 * 100.0;
              int progressPercent = (int)percent;
              progressPercent = (progressPercent > 100 ? 100 : progressPercent);
              progressBar1.Value = progressPercent;
          }
          while (DateTime.Now < startTime.AddSeconds(10));

          startButton.Enabled = true;
          cancelButton.Enabled = false;
     }
}

Now, for the purposes of the progress bar you're okay, because you can use the new BackgroundWorker class.  This class exposes a ProgressChanged and RunWorkerCompleted that should allow you to perform what you need.  The ReportProgress method raises the ProgressChanged event and it has two overloads.  The first simply provides an integer progress value.  But, the second overload adds a state argument that can be any object.

I'm going to look at this a little more.  I have a good idea why Microsoft decided to change the way this works.  But, I think I like being able to shoot myself in the foot if I so choose.  I have mixed feelings on this.

Print | posted on Sunday, November 06, 2005 3:52 PM |

Feedback

Gravatar

# re: Difference with Threading

This isn't thread-safe code and should fail, but in 1.1 you can get away with it. It's awesome that MS decided to throw an exception in 2.0 to require thread-safe code. Look for Control.InvokeRequired(), Control.BeginInvoke(), and Control.Invoke(). Calling these static methods allow interaction with a control created on the UI thread from a worker thread. Google for Control.InvokeRequired and you should find a good example.
11/6/2005 8:37 PM | Mike H
Gravatar

# re: Difference with Threading

It certainly is not thread-safe code. My point of disagreement is that it shouldn't fail. Thanks for the information on the invoke methods.
11/7/2005 4:52 AM | Anthony Trudaeu
Gravatar

# re: Difference with Threading

Sure enough, you can use the invoke methods to call delegates back in the Form or wherever to perform thread-safe cross-thread operations. I did notice that in the 2.0 code my ProcessSomething method seemed to block the UI thread (e.g. I couldn't click the Cancel button) unless I added a line within the loop on the background thread to put the Thread to sleep for a short period of time. Even 5ms seemed to be enough time.
11/7/2005 6:14 AM | Anthony Trudeau
Gravatar

# re: Difference with Threading

For Short Fix Use This :

Control.CheckForIllegalCrossThreadCalls = false

Regrads
12/19/2005 5:38 AM | Reza Ghorbani
Gravatar

# re: Difference with Threading

Awesome thanks!
12/19/2005 6:11 AM | Anthony Trudeau

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 8 and 7 and type the answer here:

Powered by: