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
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C#
  4. Communicating with a Thread

Communicating with a Thread

Scheduled Pinned Locked Moved C#
questioncsharpc++helptutorial
13 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.
  • D Demian Panello

    Hi!. I wrote an application that start a thread that read some data from the communication port. The problem is that I want to put the data in a textbox, (text1), and I don't know how to do that:confused:. In C++ I just use a global variable, but how can I define a global variable in Visual C#. How can I get data from the thread?. Thank you very much. Demian.

    H Offline
    H Offline
    Heath Stewart
    wrote on last edited by
    #3

    Use Control.InvokeRequired and Control.Invoke from threads other than the thread on which the control was created. Global variables are also not a very good way unless you use good locking when reading/writing from/to them (the lock keyword in C# is a simple way to do this using a monitor). To use a global variable, you can always use a static property or, if your threaded method is a method defined on the Control class that contains your TextBox, just use a private variable (and be sure to lock it). To write to the text box, make sure your thread class or procedure has a reference to your TextBox (for example, you could thread a single method in your class which contains the TextBox reference). If you're not sure if your method would be threaded or not, use the code below (otherwise eliminate the check for Control.InvokeRequired):

    private void ReadFromPort()
    {
    string value = value from port;
    if (text1.InvokeRequired)
    {
    // This isn't really optimized, but it's only an example...
    Type t = text1.GetType();
    MethodInfo info = t.GetProperty("Text").GetSetMethod();
    Delegate d = Delegate.CreateDelegate(t, info);
    text1.Invoke(d, new object[] {value});
    }
    else text1.Text = value;
    }

    Microsoft MVP, Visual C# My Articles

    J 1 Reply Last reply
    0
    • J Judah Gabriel Himango

      Global variables are looked down upon in the object-oriented world, and are not allowed in Java or C#. If you want to place text inside the textbox, just pass your textbox instance to the object reading your communication port. Also note that Windows Forms controls are single threaded in nature; it's a no-no to modify them from a thread other than the thread that owns the handle to the control (ie the thread that the control was created on). Fortunately for you and I, all Windows Forms controls contain a method called .Invoke that lets you call a method on the control using the thread that owns the handle. --------------------------- He who knows that enough is enough will always have enough. -Lao Tsu

      S Offline
      S Offline
      SapiensBwG
      wrote on last edited by
      #4

      sorry judah didnt get that last part! could u exemplify! thx in advance i was needing this for another app

      J 1 Reply Last reply
      0
      • S SapiensBwG

        sorry judah didnt get that last part! could u exemplify! thx in advance i was needing this for another app

        J Offline
        J Offline
        Judah Gabriel Himango
        wrote on last edited by
        #5

        See Heath's post below. --------------------------- He who knows that enough is enough will always have enough. -Lao Tsu

        1 Reply Last reply
        0
        • H Heath Stewart

          Use Control.InvokeRequired and Control.Invoke from threads other than the thread on which the control was created. Global variables are also not a very good way unless you use good locking when reading/writing from/to them (the lock keyword in C# is a simple way to do this using a monitor). To use a global variable, you can always use a static property or, if your threaded method is a method defined on the Control class that contains your TextBox, just use a private variable (and be sure to lock it). To write to the text box, make sure your thread class or procedure has a reference to your TextBox (for example, you could thread a single method in your class which contains the TextBox reference). If you're not sure if your method would be threaded or not, use the code below (otherwise eliminate the check for Control.InvokeRequired):

          private void ReadFromPort()
          {
          string value = value from port;
          if (text1.InvokeRequired)
          {
          // This isn't really optimized, but it's only an example...
          Type t = text1.GetType();
          MethodInfo info = t.GetProperty("Text").GetSetMethod();
          Delegate d = Delegate.CreateDelegate(t, info);
          text1.Invoke(d, new object[] {value});
          }
          else text1.Text = value;
          }

          Microsoft MVP, Visual C# My Articles

          J Offline
          J Offline
          Judah Gabriel Himango
          wrote on last edited by
          #6

          Keeping in mind that was example code, FYI that snippet won't work; Delegate.CreateDelegate takes a Type parameter for delegate types only. You might want to try this instead:

          private delegate void SetTextDelegate(TextBox tb, string text);

          private void ReadFromPort(TextBox tb)
          {
          string portData = ... // read from communications port

             this.SetText(tb, portData);
          

          }

          private void SetText(TextBox tb, string text)
          {
          if(tb.InvokeRequired) // if we're calling from any thread other than the one used to create the text box
          {
          tb.Invoke(new SetTextDelegate(SetText), new object[] {tb, text});
          }
          else tb.Text = text; // no invoke required
          }

          I *think* that should work. :) --------------------------- He who knows that enough is enough will always have enough. -Lao Tsu

          S D 3 Replies Last reply
          0
          • J Judah Gabriel Himango

            Keeping in mind that was example code, FYI that snippet won't work; Delegate.CreateDelegate takes a Type parameter for delegate types only. You might want to try this instead:

            private delegate void SetTextDelegate(TextBox tb, string text);

            private void ReadFromPort(TextBox tb)
            {
            string portData = ... // read from communications port

               this.SetText(tb, portData);
            

            }

            private void SetText(TextBox tb, string text)
            {
            if(tb.InvokeRequired) // if we're calling from any thread other than the one used to create the text box
            {
            tb.Invoke(new SetTextDelegate(SetText), new object[] {tb, text});
            }
            else tb.Text = text; // no invoke required
            }

            I *think* that should work. :) --------------------------- He who knows that enough is enough will always have enough. -Lao Tsu

            S Offline
            S Offline
            SapiensBwG
            wrote on last edited by
            #7

            thx for the help guys appreciate it

            1 Reply Last reply
            0
            • J Judah Gabriel Himango

              Keeping in mind that was example code, FYI that snippet won't work; Delegate.CreateDelegate takes a Type parameter for delegate types only. You might want to try this instead:

              private delegate void SetTextDelegate(TextBox tb, string text);

              private void ReadFromPort(TextBox tb)
              {
              string portData = ... // read from communications port

                 this.SetText(tb, portData);
              

              }

              private void SetText(TextBox tb, string text)
              {
              if(tb.InvokeRequired) // if we're calling from any thread other than the one used to create the text box
              {
              tb.Invoke(new SetTextDelegate(SetText), new object[] {tb, text});
              }
              else tb.Text = text; // no invoke required
              }

              I *think* that should work. :) --------------------------- He who knows that enough is enough will always have enough. -Lao Tsu

              D Offline
              D Offline
              Demian Panello
              wrote on last edited by
              #8

              Hi Lao. Thank you for you help. But, the thread method is the method that read the comm. port, so can I pass a parameter to it?, a parameter like TextBox tb?. That method is in another class, no in the class that holds the textbox, and should I pass every control as parameter that I want to write, (with data from the comm port)?. Thank you again for your time. Demian.

              1 Reply Last reply
              0
              • J Judah Gabriel Himango

                Keeping in mind that was example code, FYI that snippet won't work; Delegate.CreateDelegate takes a Type parameter for delegate types only. You might want to try this instead:

                private delegate void SetTextDelegate(TextBox tb, string text);

                private void ReadFromPort(TextBox tb)
                {
                string portData = ... // read from communications port

                   this.SetText(tb, portData);
                

                }

                private void SetText(TextBox tb, string text)
                {
                if(tb.InvokeRequired) // if we're calling from any thread other than the one used to create the text box
                {
                tb.Invoke(new SetTextDelegate(SetText), new object[] {tb, text});
                }
                else tb.Text = text; // no invoke required
                }

                I *think* that should work. :) --------------------------- He who knows that enough is enough will always have enough. -Lao Tsu

                D Offline
                D Offline
                Demian Panello
                wrote on last edited by
                #9

                The code works fine. But I must pass a textbox reference to the class constructor. And this is a very particular case, 'cause I don't know how many controls I will have, to show the data that the thread read from the comm port. Thank you Judah. Demian.

                H 1 Reply Last reply
                0
                • D Demian Panello

                  The code works fine. But I must pass a textbox reference to the class constructor. And this is a very particular case, 'cause I don't know how many controls I will have, to show the data that the thread read from the comm port. Thank you Judah. Demian.

                  H Offline
                  H Offline
                  Heath Stewart
                  wrote on last edited by
                  #10

                  This is only if your thread method is in a different class. More than likely, there's no need to do that. In both Judah's and my examples, we assumed the method that will be invoked in another thread was part of the same class, so it already has a reference to the TextBox. This is preferred unless you have some good reason for changing it. If you do, then create a new instance of another class - passing the TextBox reference into the constructor - and start a thread on a method of that class. This is unnecessary, though, because you're creating another class just to run a method in another thread? Why go to the trouble if you don't have to.

                  Microsoft MVP, Visual C# My Articles

                  D 1 Reply Last reply
                  0
                  • H Heath Stewart

                    This is only if your thread method is in a different class. More than likely, there's no need to do that. In both Judah's and my examples, we assumed the method that will be invoked in another thread was part of the same class, so it already has a reference to the TextBox. This is preferred unless you have some good reason for changing it. If you do, then create a new instance of another class - passing the TextBox reference into the constructor - and start a thread on a method of that class. This is unnecessary, though, because you're creating another class just to run a method in another thread? Why go to the trouble if you don't have to.

                    Microsoft MVP, Visual C# My Articles

                    D Offline
                    D Offline
                    Demian Panello
                    wrote on last edited by
                    #11

                    Hi! Well, I have a class hierarchy, and theses classes must keep a communication "alive" with a devices pluged in the comm port. The device, if it has no heceived a command stop the communication. That is the trouble, the thread method is a method deep int the hierarchy. Thank you for your time. Demian.

                    H 1 Reply Last reply
                    0
                    • D Demian Panello

                      Hi! Well, I have a class hierarchy, and theses classes must keep a communication "alive" with a devices pluged in the comm port. The device, if it has no heceived a command stop the communication. That is the trouble, the thread method is a method deep int the hierarchy. Thank you for your time. Demian.

                      H Offline
                      H Offline
                      Heath Stewart
                      wrote on last edited by
                      #12

                      Like I said, then, either pass the TextBox reference into the class's constructor or set a property before you start the thread on a method of that class.

                      Microsoft MVP, Visual C# My Articles

                      D 1 Reply Last reply
                      0
                      • H Heath Stewart

                        Like I said, then, either pass the TextBox reference into the class's constructor or set a property before you start the thread on a method of that class.

                        Microsoft MVP, Visual C# My Articles

                        D Offline
                        D Offline
                        Demian Panello
                        wrote on last edited by
                        #13

                        Hi. Yes, that works, but there's no relation between the classes hierarchy and a control as reference in a constructor or in a property. Theses are communication protocol classes, it's so weird to find a control reference in their definitions. I loss the essence of the class hierarchy just putting a textbox in the definitions. That's the problem. Thank you very much for your feedback. Demian.

                        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