Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. thread safe calls

thread safe calls

Scheduled Pinned Locked Moved C#
tutorialquestion
10 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Manu_81
    wrote on last edited by
    #1

    Hi, I posted this message earlier and some one posted a link to an article. It helped, but still I am confused how to do it in my scenario. I have a HomeForm (main form which has main()). In one of its meathod I have PrimeInfoThread pTh = new PrimeInfoThread(this.pictureBox1,this.panel4,this.button1,this.button3,this.SLabel); Thread t = new Thread(new ThreadStart(pTh.ThreadProc)); t.Start(); PrimeInfoThread is another class as follows public class PrimeInfoThread { private System.Windows.Forms.PictureBox hPic ; private System.Windows.Forms.Panel hPan ; private System.Windows.Forms.Button but1 ; private System.Windows.Forms.Button but2 ; private System.Windows.Forms.Label slab ; // The constructor public PrimeInfoThread(System.Windows.Forms.PictureBox hP, System.Windows.Forms.Panel hpanel, System.Windows.Forms.Button b1, System.Windows.Forms.Button b2, System.Windows.Forms.Label Sl) { hPic = hP; hPan = hpanel; but1 = b1; but2 = b2; slab = Sl; } public void ThreadProc() { EnumGetEDID InitEnumObj = new EnumGetEDID(); InitEnumObj.AppInitEnum(slab); hPic.Hide(); hPan.Hide(); but1.Show(); but2.Show(); } } In threadProc I call another class EnumGetEDID and call AppInitEnum(slab) where I pass the label. Inside AppInitEnum() I do 'slab.Text' to set the text values. Now how do I make this Thread safe. Can anyone show it in my code. Thanks a lot.

    K 1 Reply Last reply
    0
    • M Manu_81

      Hi, I posted this message earlier and some one posted a link to an article. It helped, but still I am confused how to do it in my scenario. I have a HomeForm (main form which has main()). In one of its meathod I have PrimeInfoThread pTh = new PrimeInfoThread(this.pictureBox1,this.panel4,this.button1,this.button3,this.SLabel); Thread t = new Thread(new ThreadStart(pTh.ThreadProc)); t.Start(); PrimeInfoThread is another class as follows public class PrimeInfoThread { private System.Windows.Forms.PictureBox hPic ; private System.Windows.Forms.Panel hPan ; private System.Windows.Forms.Button but1 ; private System.Windows.Forms.Button but2 ; private System.Windows.Forms.Label slab ; // The constructor public PrimeInfoThread(System.Windows.Forms.PictureBox hP, System.Windows.Forms.Panel hpanel, System.Windows.Forms.Button b1, System.Windows.Forms.Button b2, System.Windows.Forms.Label Sl) { hPic = hP; hPan = hpanel; but1 = b1; but2 = b2; slab = Sl; } public void ThreadProc() { EnumGetEDID InitEnumObj = new EnumGetEDID(); InitEnumObj.AppInitEnum(slab); hPic.Hide(); hPan.Hide(); but1.Show(); but2.Show(); } } In threadProc I call another class EnumGetEDID and call AppInitEnum(slab) where I pass the label. Inside AppInitEnum() I do 'slab.Text' to set the text values. Now how do I make this Thread safe. Can anyone show it in my code. Thanks a lot.

      K Offline
      K Offline
      kasik
      wrote on last edited by
      #2

      It seems to me that you're making this more complicated than it needs to be with the use of an entirely seperate class (PrimeInfoThread) to run your other thread. Why don't you just have a method in your HomeForm class called ThreadProc() and then reference the UI components (labels, buttons, etc...) without passing them to another object. You can use the ParameterizedThreadStart delegate to pass the label 'slab' - although it might make more sense to just pass the string value of its Text property if thats the only reason you need it... If you do that, then the following code should make it thread safe... This goes in the routine that starts the thread:

      Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
      t.Start(this.SLabel);

      Then this in HomeForm:

      private void ThreadProc(object data)
      {
      EnumGetEDID InitEnumObj = new EnumGetEDID();
      InitEnumObj.AppInitEnum((Label)data);
      UpdateUI();
      }

      private delegate void UpdateUIDelegate();
      private void UpdateUI()
      {
      if (this.InvokeRequired)
      {
      this.BeginInvoke(new UpdateUIDelegate(UpdateUI));
      return;
      }
      pictureBox1.Hide();
      panel4.Hide();
      button1.Show();
      button3.Show();
      }

      Hope this helps :) Oh... forgot to say that this uses .Net Framework v2, since the ParameterizedThreadStart delegate isn't available in v1.1 :doh: Cheers, Will H -- modified at 15:41 Thursday 2nd February, 2006

      E 1 Reply Last reply
      0
      • K kasik

        It seems to me that you're making this more complicated than it needs to be with the use of an entirely seperate class (PrimeInfoThread) to run your other thread. Why don't you just have a method in your HomeForm class called ThreadProc() and then reference the UI components (labels, buttons, etc...) without passing them to another object. You can use the ParameterizedThreadStart delegate to pass the label 'slab' - although it might make more sense to just pass the string value of its Text property if thats the only reason you need it... If you do that, then the following code should make it thread safe... This goes in the routine that starts the thread:

        Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
        t.Start(this.SLabel);

        Then this in HomeForm:

        private void ThreadProc(object data)
        {
        EnumGetEDID InitEnumObj = new EnumGetEDID();
        InitEnumObj.AppInitEnum((Label)data);
        UpdateUI();
        }

        private delegate void UpdateUIDelegate();
        private void UpdateUI()
        {
        if (this.InvokeRequired)
        {
        this.BeginInvoke(new UpdateUIDelegate(UpdateUI));
        return;
        }
        pictureBox1.Hide();
        panel4.Hide();
        button1.Show();
        button3.Show();
        }

        Hope this helps :) Oh... forgot to say that this uses .Net Framework v2, since the ParameterizedThreadStart delegate isn't available in v1.1 :doh: Cheers, Will H -- modified at 15:41 Thursday 2nd February, 2006

        E Offline
        E Offline
        eligazit
        wrote on last edited by
        #3

        If you use the 2.0, try to use the BackgroundWorker, it gives the abilty to update without the cross-thread exception.

        K 2 Replies Last reply
        0
        • E eligazit

          If you use the 2.0, try to use the BackgroundWorker, it gives the abilty to update without the cross-thread exception.

          K Offline
          K Offline
          kasik
          wrote on last edited by
          #4

          Thanks. I've only recently started using 2.0 in the last few days. I'll definitely look into that one. Cheers, Will H

          1 Reply Last reply
          0
          • E eligazit

            If you use the 2.0, try to use the BackgroundWorker, it gives the abilty to update without the cross-thread exception.

            K Offline
            K Offline
            kasik
            wrote on last edited by
            #5

            I just gave the BackgroundWorker class a whirl, and I don't think it does allow you to update the UI from a seperate thread. Maybe I miss-read your meaning, but I took the C# code from the example in the MSDN library (here[^]), then I added the line this.Text = percentComplete + "%"; just after worker.ReportProgress(percentComplete); in the ComputeFibonacci method (the one that's running on the seperate thread), and this caused a System.InvalidOperationException - a cross thread exception :confused: Cheers, Will H

            D E 2 Replies Last reply
            0
            • K kasik

              I just gave the BackgroundWorker class a whirl, and I don't think it does allow you to update the UI from a seperate thread. Maybe I miss-read your meaning, but I took the C# code from the example in the MSDN library (here[^]), then I added the line this.Text = percentComplete + "%"; just after worker.ReportProgress(percentComplete); in the ComputeFibonacci method (the one that's running on the seperate thread), and this caused a System.InvalidOperationException - a cross thread exception :confused: Cheers, Will H

              D Offline
              D Offline
              Dave Kreskowiak
              wrote on last edited by
              #6

              You can only update UI controls on the thread that created them. Property updates and method calls on those controls must be marshalled back onto the UI thread. Lookup Control.Invoke for more information. RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome

              K 1 Reply Last reply
              0
              • K kasik

                I just gave the BackgroundWorker class a whirl, and I don't think it does allow you to update the UI from a seperate thread. Maybe I miss-read your meaning, but I took the C# code from the example in the MSDN library (here[^]), then I added the line this.Text = percentComplete + "%"; just after worker.ReportProgress(percentComplete); in the ComputeFibonacci method (the one that's running on the seperate thread), and this caused a System.InvalidOperationException - a cross thread exception :confused: Cheers, Will H

                E Offline
                E Offline
                eligazit
                wrote on last edited by
                #7

                To update GUI with the BackgroundWorker, you need to do the following steps: 1. When creating the wroker: public void InitWorker() { worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); worker.DoWork += new DoWorkEventHandler(worker_DoWork); } Note that I've creating new event handler to update GUI, when ever I want to set something on the GUI, I should call the ReportProgress(...) method of the worker: void worker_DoWork(object sender, DoWorkEventArgs e) { // Some long operation // ..... Thread.Sleep(2000); // Update GUI worker.ReportProgress(30); // Some long operation // ..... Thread.Sleep(2000); // Update GUI worker.ReportProgress(60); // Some long operation // ..... Thread.Sleep(2000); // Update GUI worker.ReportProgress(90); } And, on the ReportProgress handler, I can update the GUI as I want, this is beacuse the worker handles moving the OS the the right thread so it is not my problem... void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { Label label; label.Text = e.ProgressPercentage + "%"; } Note that on the ReportProgress you can send an object that will be set on the ProgressChangedEventArgs (State), in this property you can set all the values you want to update on the GUI (other than the precentage).

                K 1 Reply Last reply
                0
                • D Dave Kreskowiak

                  You can only update UI controls on the thread that created them. Property updates and method calls on those controls must be marshalled back onto the UI thread. Lookup Control.Invoke for more information. RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome

                  K Offline
                  K Offline
                  kasik
                  wrote on last edited by
                  #8

                  I know that. In this[^] thread I tried to explain that, but was told by eligazit that the BackgroundWorker class could let you get around this. Cheers, Will H

                  D 1 Reply Last reply
                  0
                  • E eligazit

                    To update GUI with the BackgroundWorker, you need to do the following steps: 1. When creating the wroker: public void InitWorker() { worker = new BackgroundWorker(); worker.WorkerReportsProgress = true; worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged); worker.DoWork += new DoWorkEventHandler(worker_DoWork); } Note that I've creating new event handler to update GUI, when ever I want to set something on the GUI, I should call the ReportProgress(...) method of the worker: void worker_DoWork(object sender, DoWorkEventArgs e) { // Some long operation // ..... Thread.Sleep(2000); // Update GUI worker.ReportProgress(30); // Some long operation // ..... Thread.Sleep(2000); // Update GUI worker.ReportProgress(60); // Some long operation // ..... Thread.Sleep(2000); // Update GUI worker.ReportProgress(90); } And, on the ReportProgress handler, I can update the GUI as I want, this is beacuse the worker handles moving the OS the the right thread so it is not my problem... void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { Label label; label.Text = e.ProgressPercentage + "%"; } Note that on the ReportProgress you can send an object that will be set on the ProgressChangedEventArgs (State), in this property you can set all the values you want to update on the GUI (other than the precentage).

                    K Offline
                    K Offline
                    kasik
                    wrote on last edited by
                    #9

                    Ah... i see. Thanks :) Cheers, Will H

                    1 Reply Last reply
                    0
                    • K kasik

                      I know that. In this[^] thread I tried to explain that, but was told by eligazit that the BackgroundWorker class could let you get around this. Cheers, Will H

                      D Offline
                      D Offline
                      Dave Kreskowiak
                      wrote on last edited by
                      #10

                      It doesn't "get around it". It just fire an event on the correct thread. It insulates you from the details of getting code that modifies a UI control to run on the correct thread. RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups