user721807
user721807

Reputation: 85

Update treeview from another thread

I'm quite new to threads in c# (WPF) and since I've implemented some label and progressbar update successfully, I do not understand Why when I try to add items to the treeView of my GUI from another class called in a separate thread I get an exception:

An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll

Additional information: The calling thread cannot access this object because a different thread owns it.

My update treeview code is this:

private void updateTreeView(TreeView tree, List<TreeViewItem> items, Boolean clear) {
            tree.Dispatcher.Invoke(new Action(() => {
                if (clear) {
                    tree.Items.Clear();
                }
                ItemCollection treeitems = tree.Items;
                foreach (TreeViewItem item in items) {
                    treeitems.Dispatcher.Invoke(new Action(() => {
                        treeitems.Add(item);
                    }));
                }
                tree.ItemsSource = treeitems;
            }));
        }

And the exception points at the line:

treeitems.Add(item);

Thanks in advance.

Upvotes: 1

Views: 3659

Answers (2)

DoomVroom
DoomVroom

Reputation: 327

This is a really old question but I figured I would answer it. You have two dispatchers in your sample. You have a treeview that you are getting its thread and a list that seems to be created in a different thread.

But the code should look more like this. Sorry about the VB in this case I'm using a delegate inside the invoke.

 tree.Dispatcher.BeginInvoke(Sub()
          Dim node = new TreeViewItem() With {.Header = "Header"}
          tree.items.add(node)
                             End Sub)

I am not jumping out of the UI thread to add the node like in the original question.

Upvotes: 0

cYOUNES
cYOUNES

Reputation: 936

you can use the following :

 delegate void DUpdateTreeView(TreeView tree, List<TreeViewItem> items, Boolean clear);
 private void UpdataTreeView(TreeView tree, List<TreeViewItem> items, Boolean clear)
    {
        if (tree.InvokeRequired)
        {
            DUpdateTreeView d = new DUpdateTreeView(UpdataTreeView);
            // replace this by the main form object if the function doesn't in the main form class 
            this.Invoke(d, new object[] { tree, items, clear }); 
        }
        else
        {
            if (clear)
            {
                tree.Items.Clear();
            }
            else
            {
                // Here you can add the items to the treeView
                /***
                ItemCollection treeitems = tree.Items;
                foreach (TreeViewItem item in items)
                {
                    treeitems.Dispatcher.Invoke(new Action(() =>
                    {
                        treeitems.Add(item);
                    }));
                }
                tree.ItemsSource = treeitems;
                ***/
            }
        }
    }

Upvotes: 1

Related Questions