CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Aug 2009
    Posts
    20

    need help with cross-thread delagates

    hi, i have went through countless examples of how to use delegates, and still no success
    here is my problem:

    WFA application
    Code:
    //myClassA.cs
    class myClassA 
    {
         private AddLabel(string text) // add few labels on the Panel which is placed on the form
         {
               // got ref to panel 'p' so i just call
               p.Controls.Add( //my new label);
         }
    }
    Code:
    //myClassB.cs
    class myClassB 
    {
          public void OnDataReceived // receiving data from socket, new thread
         {       
              now i need to call method from myClassA - AddLabel("some text")
              to add new label on the panel,   how ?
         }
    }
    Code:
    //Form1.cs
    public partial class Form1 : Form
    {
          private myClassA objA;
          private myClassB objB;
    
         // i can call objA.AddLabel and its working fine, but i need to call that method inside myClassB
    }
    Last edited by sv13; January 16th, 2010 at 02:54 PM.

  2. #2
    Join Date
    Aug 2009
    Posts
    20

    Re: need help with cross-thread delagates

    finally got it to work, dont know if its best solution but..

    Code:
    //myClassA.cs
    class myClassA 
    {
          i have ref to Form1.AddLabelDelegate addLabelDelegate;
         private AddLabel(string text) // add few labels on the Panel which is placed on the form
         {
               // got ref to panel 'p' so i just call
               p.Invoke(addLabelDelegate, new object[] { "text" });
         }
    }
    Code:
    //myClassB.cs
    class myClassB 
    {
          i have ref to myClassA ojbA
          public void OnDataReceived // receiving data from socket, new thread
         {       
              objA.AddLabel("text");
         }
    }
    Code:
    //Form1.cs
    public partial class Form1 : Form
    {
          private myClassA objA;
          private myClassB objB;
          
            public delegate void AddLabelDelegate(string text);
            public AddLabelDelegate AddLabel;
            public void AddLabelMethod(string text) {
                panel.Controls.Add(//.... add new label);
                }
            }
    
            public Form1()
            {
                InitializeComponent();
    
                AddLabel = new AddLabelDelegate(AddLabelMethod);    
            }
    }

  3. #3
    Join Date
    Jan 2010
    Posts
    1,133

    Re: need help with cross-thread delagates

    In order for MyClassB to be able to call a method form MyClassA, it must have some sort of reference to it.

    Make AddLabel() public, and add a member field to MyClassB referencing an instance of MyClassA - objA in your case. You can initialize it in the constructor or using some property/method (making sure it’s done before OnDataRecived() is executed). Then all you need to do is to use the member field to call AddLabel().

    Another way would be to use events, where MyClassB would have an event named something like DataRecived, which would hold a delegate for any method that should do something when the event is fired (thus also being able to directly reference an instance method of MyClassA). In this case, MyClassA would most likely be the one responsible for the registration of its method with the event, and it would probably have to hold a reference to MyClassB (or it could have a specialized public registration method that would take a parameter of MyClassB-type). The event’s type (the type of delegates it accepts) would force (better: standardize) the method’s signature, so you can send any data you require in the same manner, to any class.

    I’m not saying one way is better than the other, but for what you want to accomplish, try the first way first (somewhat less work, and you’ll probably get a better understanding of how it’s done).

  4. #4
    Join Date
    Jan 2010
    Posts
    1,133

    Re: need help with cross-thread delagates

    Oh, you figured it out. Ok.
    Maybe you've complicated it a bit, unnecessary I'd add, but what's important is that it works.

  5. #5
    Join Date
    Jan 2010
    Posts
    1,133

    Re: need help with cross-thread delagates

    Ok, I have to comment on your code a little, just to clarify what I meant when I said you complicated it a bit.
    I was thinking to leave everything as is, but I couldn’t help it – it’s stronger than me.

    Take a look what you did:
    • Form1 has member fields referencing instances of MyClassA and MyClassB. Ok.
    • Form1 also has a delegate AddLabelDelegate referencing it’s own method called AddLabelMethod(...), which adds a label to a panel Form1 owns.
    • Now, MyClassB has a member field objA referencing the same instance of MyClassA as your Form1, and when it receives data it calls objA.AddLabel(string). But, this method is declared private, so this call is impossible – it shouldn’t even compile. So, unless you typed it wrong, this won’t work.
    • Assuming that the AddLabel(...) method of MyClassA is, in fact, public, after the call to it is made, you use the Invoke(...) method of Panel class to finally execute AddLabelMethod(...) of Form1.

    There’s a lot of unnecessary indirection. Look at the chain of exec:
    OnDataRecived() -> objA.AddLabel(...) -> p.Invoke(...) -> (some framework methods) -> AddLabelMethod(...) -> panel.Controls.Add(...)


    Now, if p and panel reference the same object, why not just call p.Controls.Add()?
    If they aren’t, that means that you have an instance of Panel that you use for nothing more but to call it’s Invoke() method, which is really a waste of an object.

    Furthermore, if MyClassA does nothing else but add an entry to your panel, then there’s no much need for this class. You can simply reference your form (the form must somehow expose its panel), or just the panel (which is maybe better in this case) in your MyClassB, and do the update inside OnDataRecived(), reducing the chain to:

    OnDataRecived() -> panel.Controls.Add(...).


    Note thet in this case, there's no need for the AddLabelDelegate either.

    I hope it helps.
    Last edited by TheGreatCthulhu; January 17th, 2010 at 10:30 AM.

  6. #6
    Join Date
    Aug 2009
    Posts
    20

    Re: need help with cross-thread delagates

    hi, thanks for reply, you put a lot of efforts, and i appreciate it

    Assuming that the AddLabel(...) method of MyClassA is, in fact, public
    yes it is , sry my mistake

    but, i can not call p.Controls.Add() in myClassA AddLabel because when myClassB actually calls objA.AddLabel, it is called from separate thread, so i will get cross-thread exception (controls are created in form1 thread and i am trying to access them from thread started in myClassB)

  7. #7
    Join Date
    Jan 2010
    Posts
    1,133

    Re: need help with cross-thread delagates

    Quote Originally Posted by sv13 View Post
    but, i can not call p.Controls.Add() in myClassA AddLabel because [...] it is called from separate thread, so i will get cross-thread exception
    You are absolutely right. I apologize, my bad. It happens…
    It’s an internal mechanism windows controls have to make sure that a class instance is kept in a consistent state in a multithreaded setting.

    But still, it’s only a detail, why not have a panel variable in MyClassB and call panel.Invoke(...) there?
    Don’t get me wrong, the way you did it is perfectly legal; I’m just saying it only makes sense if there’s a reason for it. A general good practice is to make your code only as complex as it needs to be, since it makes it easier to maintain (and read).
    It’s, naturally, totally up to you.

    P.S. Does anyone on the forum know how Control.Invoke(...) actually works? Does it use Dispatcher.Invoke(...)?
    Last edited by TheGreatCthulhu; January 18th, 2010 at 06:00 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured