Cross Thread Communications

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • AliR \(VC++ MVP\)

    Cross Thread Communications

    Hi everyone,

    I have a Socket derived class that parses the received data into a message,
    populates a object with that information and then tries to send an event to
    inform the owner of the socket that there is message to be processed. But
    this is not working as the socket receiver method seems to be in a different
    thread then the form that owns the socket.

    The receive callback gets the data from the socket and process the
    information, once it constructs a full message from it then it calls a
    delegate if the delegate is set.

    The method that handles this event needs to change some controls on the form
    and when I do that I get the exception:
    Cross-thread operation not valid: Control 'syncButton' accessed from a
    thread other than the thread it was created on.

    I would appreciate any suggestions on solving this.

    class LSSocket : Socket
    {
    public event ProcessMessageH andler ProcessMessageE vent;

    public void OnReceiveData(I AsyncResult)
    {
    ....
    if (ProcessMessage Event != null)
    {
    ProcessMessageE vent(this, new ProcessMessageA rgs(Msg));
    }
    }
    }

    class ProcessMessageA rgs : System.EventArg s
    {
    public ProcessMessageA rgs(LSMessage msg)
    {
    this.msg = msg;
    }
    public LSMessage msg;
    }
    delegate void ProcessMessageH andler(object sender, ProcessMessageA rgs
    e);

    I would have had to use PostThreadMessa ge in native windows development, but
    I can't figure out what I need to use in this situation.

    AliR.


  • Ignacio Machin ( .NET/ C# MVP )

    #2
    Re: Cross Thread Communications

    On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.no spamwrote:
    Hi everyone,
    >
    I have a Socket derived class that parses the received data into a message,
    populates a object with that information and then tries to send an event to
    inform the owner of the socket that there is message to be processed. But
    this is not working as the socket receiver method seems to be in a different
    thread then the form that owns the socket.
    >
    The receive callback gets the data from the socket and process the
    information, once it constructs a full message from it then it calls a
    delegate if the delegate is set.
    >
    The method that handles this event needs to change some controls on the form
    and when I do that I get the exception:
    Cross-thread operation not valid: Control 'syncButton' accessed from a
    thread other than the thread it was created on.
    >
    I would appreciate any suggestions on solving this.
    >
    class LSSocket : Socket
    {
    public event ProcessMessageH andler ProcessMessageE vent;
    >
    public void OnReceiveData(I AsyncResult)
    {
    ....
    if (ProcessMessage Event != null)
    {
    ProcessMessageE vent(this, new ProcessMessageA rgs(Msg));
    }
    }
    }
    >
    class ProcessMessageA rgs : System.EventArg s
    {
    public ProcessMessageA rgs(LSMessage msg)
    {
    this.msg = msg;
    }
    public LSMessage msg;
    }
    delegate void ProcessMessageH andler(object sender, ProcessMessageA rgs
    e);
    >
    I would have had to use PostThreadMessa ge in native windows development, but
    I can't figure out what I need to use in this situation.
    >
    AliR.
    Use Control.Invoke to execute the event in the UI thread.

    Comment

    • AliR \(VC++ MVP\)

      #3
      Re: Cross Thread Communications

      "Ignacio Machin ( .NET/ C# MVP )" <ignacio.machin @gmail.comwrote in
      message
      news:1fc73414-8e5e-4fd5-91cf-3c2cd36d9dd1@m4 4g2000hsc.googl egroups.com...
      On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.no spamwrote:
      >Hi everyone,
      >>
      >I have a Socket derived class that parses the received data into a
      >message,
      >populates a object with that information and then tries to send an event
      >to
      >inform the owner of the socket that there is message to be processed.
      >But
      >this is not working as the socket receiver method seems to be in a
      >different
      >thread then the form that owns the socket.
      >>
      >The receive callback gets the data from the socket and process the
      >information, once it constructs a full message from it then it calls a
      >delegate if the delegate is set.
      >>
      >The method that handles this event needs to change some controls on the
      >form
      >and when I do that I get the exception:
      >Cross-thread operation not valid: Control 'syncButton' accessed from a
      >thread other than the thread it was created on.
      >>
      >I would appreciate any suggestions on solving this.
      >>
      > class LSSocket : Socket
      > {
      > public event ProcessMessageH andler ProcessMessageE vent;
      >>
      > public void OnReceiveData(I AsyncResult)
      > {
      > ....
      > if (ProcessMessage Event != null)
      > {
      > ProcessMessageE vent(this, new
      >ProcessMessage Args(Msg));
      > }
      > }
      > }
      >>
      > class ProcessMessageA rgs : System.EventArg s
      > {
      > public ProcessMessageA rgs(LSMessage msg)
      > {
      > this.msg = msg;
      > }
      > public LSMessage msg;
      > }
      > delegate void ProcessMessageH andler(object sender, ProcessMessageA rgs
      >e);
      >>
      >I would have had to use PostThreadMessa ge in native windows development,
      >but
      >I can't figure out what I need to use in this situation.
      >>
      >AliR.
      >
      Use Control.Invoke to execute the event in the UI thread.
      I looked at Control.Invoke, but wasn't really sure where it would apply. A
      little more explanation would be great.

      Are you saying that I have to use that in event hander method in my form
      class to do the UI manipulation? Or am I supposed to use it in place of the
      event hander call? Or am I supposed to call the event handler delegate
      using the Invoke method?

      Here is the event handler method:
      public void ProcessMessage( object sender, ProcessMessageA rgs e)
      {
      switch (e.msg.m_Comman d)
      {
      case MSG_SERVERIP: ServerIP = e.msg.m_Address ;
      ServerPort = 29308;
      syncButton.Enab led = true;
      break;
      default: Debug.Print("Oh Oh");
      break;
      }
      }

      AliR


      Comment

      • AliR \(VC++ MVP\)

        #4
        Re: Cross Thread Communications

        "AliR (VC++ MVP)" <AliR@online.no spamwrote in message
        news:QW0mk.3489 6$ZE5.11669@nlp i061.nbdc.sbc.c om...
        "Ignacio Machin ( .NET/ C# MVP )" <ignacio.machin @gmail.comwrote in
        message
        news:1fc73414-8e5e-4fd5-91cf-3c2cd36d9dd1@m4 4g2000hsc.googl egroups.com...
        >On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.no spamwrote:
        >>Hi everyone,
        >>>
        >>I have a Socket derived class that parses the received data into a
        >>message,
        >>populates a object with that information and then tries to send an event
        >>to
        >>inform the owner of the socket that there is message to be processed.
        >>But
        >>this is not working as the socket receiver method seems to be in a
        >>different
        >>thread then the form that owns the socket.
        >>>
        >>The receive callback gets the data from the socket and process the
        >>information , once it constructs a full message from it then it calls a
        >>delegate if the delegate is set.
        >>>
        >>The method that handles this event needs to change some controls on the
        >>form
        >>and when I do that I get the exception:
        >>Cross-thread operation not valid: Control 'syncButton' accessed from a
        >>thread other than the thread it was created on.
        >>>
        >>I would appreciate any suggestions on solving this.
        >>>
        >> class LSSocket : Socket
        >> {
        >> public event ProcessMessageH andler ProcessMessageE vent;
        >>>
        >> public void OnReceiveData(I AsyncResult)
        >> {
        >> ....
        >> if (ProcessMessage Event != null)
        >> {
        >> ProcessMessageE vent(this, new
        >>ProcessMessag eArgs(Msg));
        >> }
        >> }
        >> }
        >>>
        >> class ProcessMessageA rgs : System.EventArg s
        >> {
        >> public ProcessMessageA rgs(LSMessage msg)
        >> {
        >> this.msg = msg;
        >> }
        >> public LSMessage msg;
        >> }
        >> delegate void ProcessMessageH andler(object sender,
        >>ProcessMessag eArgs
        >>e);
        >>>
        >>I would have had to use PostThreadMessa ge in native windows development,
        >>but
        >>I can't figure out what I need to use in this situation.
        >>>
        >>AliR.
        >>
        >Use Control.Invoke to execute the event in the UI thread.
        >
        I looked at Control.Invoke, but wasn't really sure where it would apply.
        A little more explanation would be great.
        >
        Are you saying that I have to use that in event hander method in my form
        class to do the UI manipulation? Or am I supposed to use it in place of
        the event hander call? Or am I supposed to call the event handler
        delegate using the Invoke method?
        >
        Here is the event handler method:
        public void ProcessMessage( object sender, ProcessMessageA rgs e)
        {
        switch (e.msg.m_Comman d)
        {
        case MSG_SERVERIP: ServerIP = e.msg.m_Address ;
        ServerPort = 29308;
        syncButton.Enab led = true;
        break;
        default: Debug.Print("Oh Oh");
        break;
        }
        }
        >
        AliR
        >
        I think I got it. (Correctly or not I don't know.)
        Beside the event member, I added a parent form object to the class of type
        Control.

        delegate void ProcessMessageH andler(LSMessag e Msg);
        class LSSocket : Socket
        {
        public event ProcessMessageH andler ProcessMessageE vent;
        public Form ParentForm = null;

        public void OnReceiveData(I AsyncResult)
        {
        //pares data into a LSMessage class (Msg)
        ....
        if (ProcessMessage Event != null && ParentForm != null)
        {
        // ProcessMessageE vent(this, new
        ProcessMessageA rgs(Msg));
        ParentForm.Invo ke(ProcessMessa geEvent,Msg);
        }
        }
        .....
        }

        Hopefully this is the right way of doing it.

        AliR.


        Comment

        • Peter Duniho

          #5
          Re: Cross Thread Communications

          On Tue, 05 Aug 2008 11:25:58 -0700, AliR (VC++ MVP) <AliR@online.no spam>
          wrote:
          [...]
          public void ProcessMessage( object sender, ProcessMessageA rgs e)
          {
          switch (e.msg.m_Comman d)
          {
          case MSG_SERVERIP: ServerIP = e.msg.m_Address ;
          ServerPort = 29308;
          syncButton.Enab led = true;
          break;
          default: Debug.Print("Oh Oh");
          break;
          }
          }
          Try:

          public void ProcessMessage( object sender, ProcessMessageA rgs e)
          {
          switch (e.msg.m_Comman d)
          {
          case MSG_SERVERIP: ServerIP = e.msg.m_Address ;
          ServerPort = 29308;
          syncButton.Invo ke((MethodInvok er)delegate {
          syncButton.Enab led = true } );
          break;
          default: Debug.Print("Oh Oh");
          break;
          }
          }

          Not only does that avoid having to track a specific parent control in your
          event-raising class, IMHO it's better for the GUI-specific stuff to stay
          in the GUI-specific class.

          Pete

          Comment

          • AliR \(VC++ MVP\)

            #6
            Re: Cross Thread Communications


            "Peter Duniho" <NpOeStPeAdM@nn owslpianmk.comw rote in message
            news:op.uffhuqi m8jd0ej@petes-computer.local. ..
            On Tue, 05 Aug 2008 11:25:58 -0700, AliR (VC++ MVP) <AliR@online.no spam>
            wrote:
            >
            >[...]
            > public void ProcessMessage( object sender, ProcessMessageA rgs e)
            > {
            > switch (e.msg.m_Comman d)
            > {
            > case MSG_SERVERIP: ServerIP = e.msg.m_Address ;
            > ServerPort = 29308;
            > syncButton.Enab led = true;
            > break;
            > default: Debug.Print("Oh Oh");
            > break;
            > }
            > }
            >
            Try:
            >
            public void ProcessMessage( object sender, ProcessMessageA rgs e)
            {
            switch (e.msg.m_Comman d)
            {
            case MSG_SERVERIP: ServerIP = e.msg.m_Address ;
            ServerPort = 29308;
            syncButton.Invo ke((MethodInvok er)delegate {
            syncButton.Enab led = true } );
            break;
            default: Debug.Print("Oh Oh");
            break;
            }
            }
            >
            Not only does that avoid having to track a specific parent control in your
            event-raising class, IMHO it's better for the GUI-specific stuff to stay
            in the GUI-specific class.
            >
            Pete
            Very cool, thank you. I had no idea how to use Invoke! As you can tell
            I'm a newbee.

            AliR.


            Comment

            • Ignacio Machin ( .NET/ C# MVP )

              #7
              Re: Cross Thread Communications

              On Aug 5, 2:25 pm, "AliR \(VC++ MVP\)" <A...@online.no spamwrote:
              "Ignacio Machin ( .NET/ C# MVP )" <ignacio.mac... @gmail.comwrote in
              messagenews:1fc 73414-8e5e-4fd5-91cf-3c2cd36d9dd1@m4 4g2000hsc.googl egroups.com...
              >
              >
              >
              On Aug 5, 12:48 pm, "AliR \(VC++ MVP\)" <A...@online.no spamwrote:
              Hi everyone,
              >
              I have a Socket derived class that parses the received data into a
              message,
              populates a object with that information and then tries to send an event
              to
              inform the owner of the socket that there is message to be processed.
              But
              this is not working as the socket receiver method seems to be in a
              different
              thread then the form that owns the socket.
              >
              The receive callback gets the data from the socket and process the
              information, once it constructs a full message from it then it calls a
              delegate if the delegate is set.
              >
              The method that handles this event needs to change some controls on the
              form
              and when I do that I get the exception:
              Cross-thread operation not valid: Control 'syncButton' accessed from a
              thread other than the thread it was created on.
              >
              I would appreciate any suggestions on solving this.
              >
              class LSSocket : Socket
              {
              public event ProcessMessageH andler ProcessMessageE vent;
              >
              public void OnReceiveData(I AsyncResult)
              {
              ....
              if (ProcessMessage Event != null)
              {
              ProcessMessageE vent(this, new
              ProcessMessageA rgs(Msg));
              }
              }
              }
              >
              class ProcessMessageA rgs : System.EventArg s
              {
              public ProcessMessageA rgs(LSMessage msg)
              {
              this.msg = msg;
              }
              public LSMessage msg;
              }
              delegate void ProcessMessageH andler(object sender, ProcessMessageA rgs
              e);
              >
              I would have had to use PostThreadMessa ge in native windows development,
              but
              I can't figure out what I need to use in this situation.
              >
              AliR.
              >
              Use Control.Invoke to execute the event in the UI thread.
              >
              I looked at Control.Invoke, but wasn't really sure where it would apply. A
              little more explanation would be great.
              >
              Are you saying that I have to use that in event hander method in my form
              class to do the UI manipulation?
              Yes, in windows forms the controls should only be accessed from the
              UI thread. You can make an event to be executed in the UI thread (or
              more exactly in the control's creation thread, that in the current
              implementation is the UI) by using Control.Invoke.

              Invoke what does is put a message in the message pump that will be
              executed as any other message in a win. app.

              Comment

              Working...