Results 1 to 8 of 8

Thread: [RESOLVED] TreeView -- Load nodes with multithreading

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Sep 2002
    Posts
    146

    Resolved [RESOLVED] TreeView -- Load nodes with multithreading

    I have a treeview control with 3 levels of nodes. Domains, users and folders.

    When a node gets expanded, I want to load its children dynamically and simultaneously calculate the size of each child in a separate thread so that it will not freeze the GUI.


    Code:
            public void treeView1_AfterExpand(object sender, TreeViewEventArgs e)
            {
                switch (e.Node.Level)  //Domain level
                {
                    case 0:  
    
                        string domin = e.Node.Name;
                        List<string> userList = getUsers(domain);
    		                      
                        foreach (string user in userList)
                        {
                                                    
                            TreeNode temp = new TreeNode();
                            temp.Name = user
                            temp.Text = user + " (Calculating size) ";
    
                            ThreadContainer1 threadcontainer = new ThreadContainer1(e.Node, domain, user);
                            Thread thread1 = new Thread(new ThreadStart(threadcontainer.GetUserSize));
                            thread1.Start();
    
                            e.Node.Nodes.Add(temp);
                        }                    
    
                        break;
    
                    case 1: //User level
    		    string domain = e.Node.Parent.Name;
    		    string user = e.Node.Name;
                       
                        List<string> folderList = getFolders(domain, user);
    
                        foreach (string folder in folders)
                        {
                           
                            TreeNode temp = new TreeNode();                        
                            temp.Name = folder;
    			temp.Text = user + " (Calculating size) ";
    
    			ThreadContainer2 threadcontainer = new ThreadContainer2(e.Node, domain, user, folder);
                            Thread thread1 = new Thread(new ThreadStart(threadcontainer.GetUFolderSize));
    			thread1.Start();                        
                           
                            e.Node.Nodes.Add(temp);
                        }
    
                        break;
    
                }           
    
            }
    Each thread is supposed to update the referenced node to display the corresponding size after calculating for a while.

    However "Cross-thread operation not valid with threading" exception gets thrown whenever a thread tries to access the referenced node.

    I googled the issue and found out about delegate.
    http://www.shabdar.org/cross-thread-...not-valid.html

    But the problem is that node is not a control. So it does not have Invoke() method.

    Anyone knows how to solve this problem?
    Last edited by winterslam; Jul 2nd, 2009 at 11:56 PM.

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: TreeView -- Load nodes with multithreading

    The TreeView is a control. It has an Invoke method.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Sep 2002
    Posts
    146

    Re: TreeView -- Load nodes with multithreading

    Quote Originally Posted by jmcilhinney View Post
    The TreeView is a control. It has an Invoke method.
    But I'm passing node, which i not a control, to the thread container.


    Should I pass the reference of the TreeView control itself to the thread container? But it gets ugly since the thread is not aware of which 'node' to update unless some positional information about the node is passed too.

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: TreeView -- Load nodes with multithreading

    Just call Invoke on the TreeView and pass whatever you want. It really doesn't matter what you call Invoke on. That's just a way to cross the thread boundary. Just as long as the control you call it on was created on the right thread it doesn't matter. You can call Invoke on the form if you want, or the TreeView, or even some CheckBox that you don't even use. It doesn't matter.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Sep 2002
    Posts
    146

    Re: TreeView -- Load nodes with multithreading

    Sorry I don't get what you mean


    Mine is similar to this
    http://msdn.microsoft.com/en-us/library/a1hetckb.aspx

    The only difference is that I'm trying to update nodes of a treeview from separate threads. I'm passing referenced nodes to the respective threads.

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: TreeView -- Load nodes with multithreading

    You are trying to complicate something that isn't complicated. Just call Invoke on the TreeView. That's it.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: TreeView -- Load nodes with multithreading

    Sorry about my previous post. It was after midnight here and I was watching TV, but I should have either taken the time to post properly or not posted at all. I got the impression that you actually knew what to do but you were just baulking at doing it. Regardless, here's what I should have posted:

    1. Create a new WinForms project.
    2. Add a Button and a TreeView.
    3. Add the following code:
    Code:
    private void Form1_Load(object sender, EventArgs e)
    {
        this.button1.Click += new EventHandler(button1_Click);
    }
    
    private void button1_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(CreateNodes);
    
        t.Start();
    }
    
    private void CreateNodes()
    {
        TreeNode[] nodes = {
                               new TreeNode("Node1"),
                               new TreeNode("Node2"),
                               new TreeNode("Node3")
                           };
    
        nodes[0].Nodes.AddRange(new TreeNode[]
                                {
                                    new TreeNode("Node1.1"),
                                    new TreeNode("Node1.2"),
                                    new TreeNode("Node1.3")
                                });
    
        this.AddNodes(nodes);
    }
    
    private delegate void AddNodesCallback(TreeNode[] nodes);
    
    private void AddNodes(TreeNode[] nodes)
    {
        if (this.treeView1.InvokeRequired)
        {
            this.treeView1.Invoke(new AddNodesCallback(AddNodes), (object) nodes);
        }
        else
        {
            this.treeView1.Nodes.AddRange(nodes);
        }
    }
    4. Run the project.
    5. Click the Button.

    As you can see, the TreeView is updated successfully. Now, as I said, it really doesn't matter which control you call Invoke on as long as it was created on the right thread. Invoke is only a way to cross the thread boundary. It has no bearing on what you can do when you get there. You could change that code to this:
    Code:
    private void AddNodes(TreeNode[] nodes)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new AddNodesCallback(AddNodes), (object) nodes);
        }
        else
        {
            this.treeView1.Nodes.AddRange(nodes);
        }
    }
    or even this:
    Code:
    private void AddNodes(TreeNode[] nodes)
    {
        if (this.button1.InvokeRequired)
        {
            this.button1.Invoke(new AddNodesCallback(AddNodes), (object) nodes);
        }
        else
        {
            this.treeView1.Nodes.AddRange(nodes);
        }
    }
    and it will still work because the forrm and all its controls are all owned by the same thread.

    For more information on how and why I arrived at this code, read this.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  8. #8

    Thread Starter
    Addicted Member
    Join Date
    Sep 2002
    Posts
    146

    Re: TreeView -- Load nodes with multithreading

    Thanks

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