Invoke
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6

Thread: Invoke

  1. #1
    Join Date
    Feb 2005
    Location
    Israel
    Posts
    1,475

    Invoke

    I have a class that perform several UI operations.
    The problem is that I sometimes access the class from a different thread.
    Everytime I access the class from a different thread it shouts at me that I am trying to update the GUI from a different thread, and that I should use Invoke.
    I don't mind using Invoke, but there is a catch:
    For every UI operation I need to declare a method and a delegate.
    My code looks really bad because of it. What started as a simple code will now look very intimidating.
    Take this simple code for example:
    Code:
    public void DoStaffToGUI(string text)
    {
        myTreeView.Nodes.Add(new TreeNode(text));
        myTextBox.Text = text;
        myListBox.Items.Add(text);
    }
    Now it looks like this:
    Code:
    public void DoStaffToGUI(string text)
    {
        if (!myTreeView.InvokeRequired)
             myTreeView.Nodes.Add(new TreeNode(text));
        else
             myTreeView.Invoke(new AddNodeDelegate(AddNode),new object[] {new TreeNode(text)});
        if (!myTextBox.InvokeRequired)
             myTextBox.Text = text; 
        else
             myTextBox.Invoke(new SetTextboxDelegate(SetTextbox),new object[] {text});
    
        if (!myListBox.InvokeRequired)
             myListBox.Items.Add(text);
        else
             myListBox.Invoke(new AddToListboxDelegate(AddToListbox),new object[] {text});
    
    }
    
    private delegate void AddNodeDelegate(TreeNode tn);
    private delegate void SetTextboxDelegate(string text);
    private delegate void AddToListboxDelegate(string text);
    
    private void AddNode(TreeNode tn)
    {
        myTreeView.Nodes.Add(tn);
    }
    
    private void SetTextbox(string text)
    {
        myTextbox.Text = text;
    }
    
    private void AddToListbox(string text)
    {
        myListbox.Items.Add(text);
    }
    Now that's HELL. And this is just a very simple example.
    Is there a pattern or something else that could be done?

  2. #2
    Join Date
    Apr 2005
    Location
    Norway
    Posts
    3,934

    Re: Invoke

    Quote Originally Posted by jhammer
    Now that's HELL. And this is just a very simple example.
    Well, I'm sure you can make that example even simpler. Lets try:

    1. Do we need all those if-statements?
    Code:
    public void DoStaffToGUI(string text)
    {
        if (!myTreeView.InvokeRequired)
        {
             myTreeView.Nodes.Add(new TreeNode(text));
             myTextBox.Text = text; 
             myListBox.Items.Add(text);
        }
        else
        {
             myTreeView.Invoke(new AddNodeDelegate(AddNode),new object[] {new TreeNode(text)});
             myTextBox.Invoke(new SetTextboxDelegate(SetTextbox),new object[] {text});
             myListBox.Invoke(new AddToListboxDelegate(AddToListbox),new object[] {text});
        }
    }
    
    private delegate void AddNodeDelegate(TreeNode tn);
    private delegate void SetTextboxDelegate(string text);
    private delegate void AddToListboxDelegate(string text);
    
    private void AddNode(TreeNode tn)
    {
        myTreeView.Nodes.Add(tn);
    }
    
    private void SetTextbox(string text)
    {
        myTextbox.Text = text;
    }
    
    private void AddToListbox(string text)
    {
        myListbox.Items.Add(text);
    }
    2. Do you need a delegate for every single 'instrcution'?
    Code:
    public void DoStaffToGUI(string text)
    {
        if (!myTreeView.InvokeRequired)
        {
             myTreeView.Nodes.Add(new TreeNode(text));
             myTextBox.Text = text; 
             myListBox.Items.Add(text);
        }
        else
        {
             myTreeView.Invoke(new DoMultipleDelegate(DoMultiple),new object[] {text});
        }
    }
    
    private delegate void DoMultipleDelegate(string text);
    
    private void DoMultiple(string text)
    {
        myTreeView.Nodes.Add(new TreeNode(text));
        myTextbox.Text = text;
        myListbox.Items.Add(text);
    }
    3. What about code reuse?
    Code:
    public void DoStaffToGUI(string text)
    {
        if (!myTreeView.InvokeRequired)
        {
            DoMultiple(text);
        }
        else
        {
             myTreeView.Invoke(new DoMultipleDelegate(DoMultiple),new object[] {text});
        }
    }
    
    private delegate void DoMultipleDelegate(string text);
    
    private void DoMultiple(string text)
    {
        myTreeView.Nodes.Add(new TreeNode(text));
        myTextbox.Text = text;
        myListbox.Items.Add(text);
    }
    - petter

  3. #3
    Join Date
    Feb 2005
    Location
    Israel
    Posts
    1,475

    Re: Invoke

    Wildforg, thanks for that, but you missed my point.
    The text was just as example, as each method can have different signature.

  4. #4
    Join Date
    Apr 2005
    Location
    Norway
    Posts
    3,934

    Re: Invoke

    Wildforg, thanks for that, but you missed my point.
    The text was just as example, as each method can have different signature.
    One solution could be to make a small handfull of generic delegates:
    Code:
    public delegate R ParamDelegate<R, T1>(T1 t1); // one argument
    public delegate R ParamDelegate<R, T1, T2>(T1 t1, T2 t2); // two arguments
    Then you don't need to create a specific delegate for every single function prototype:
    Code:
    public char test(bool b, int i)
    {
        return 'c';
    }
    
    // 
    new ParamDelegate<char, bool, int>(test);
    - petter

  5. #5
    Join Date
    Feb 2005
    Location
    Israel
    Posts
    1,475

    Re: Invoke

    Very interesting. I will sure give this a try.
    You save me the need to define delegates all over the place.
    However, every time I want to invoke a method still I need to write:
    Code:
        if (!myListBox.InvokeRequired)
             myListBox.Items.Add(text);
        else
             myListBox.Invoke(new ParamDelegate<void,string>(AddToList),new object[] {text})
    Any solution to that?
    Last edited by jhammer; September 4th, 2006 at 06:06 AM.

  6. #6
    Join Date
    Apr 2005
    Location
    Norway
    Posts
    3,934

    Re: Invoke

    However, every time I want to invoke a method still I need to write:
    Well, that's why we get paid... But, maybe you can add a couple more generic functions to your collection:
    Code:
    public static R Invoker<R, T1>(Control ctrl, ParamDelegate<R, T1> func, T1 t1)
    {
        if (ctrl.InvokeRequired)
            return (R)ctrl.Invoke(func, new object[] { t1 });
    
        return func(t1);
    }
    
    public static R Invoker<R, T1, T2>(Control ctrl, ParamDelegate<R, T1, T2> func, T1 t1, T2 t2)
    {
        if (ctrl.InvokeRequired)
            return (R)ctrl.Invoke(func, new object[] { t1, t2 });
    
        return func(t1, t2);
    }
    Then the function to call...
    Code:
    public char test(bool b, int c)
    {
        // do something
        return 'c';
    }
    And then to call the test function (either directly or through invoke), you do this:
    Code:
    char c = Invoker<char, bool, int>(yourControl, test, true, 3);
    Then wait for class extensions in C# v3.0, and you should be be able to write:
    Code:
    char c = yourControl.Invoker<char, bool, int>(test, true, 3);
    - petter
    Last edited by wildfrog; September 4th, 2006 at 09:13 AM. Reason: in red...

Posting Permissions

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


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This a Codeguru.com survey!


On-Demand Webinars (sponsored)