Tree view is not updating in background

1k Views Asked by At

here it is the FULL source code : http://pastebin.com/mLaGwwi0 As you will notice , the thing is to scan directories and files and populate them in a tree view. I am using background worker (the same happens with Threads class) to do that in background, while updating treeview with nodes one by one. The thing is that it is not working in background and not updating the treeview. This is the part of code which is hanging the form :

public void ListDirectory(DirectoryInfo path)
{
    treeView1.Nodes.Add(CreateDirectoryNode(path));
}

public void Addnode(DirectoryInfo dirinfo)
{
    Invoke(new AddCDAnode(ListDirectory), new object[] { dirinfo });
}

private TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
    var directoryNode = new TreeNode(directoryInfo.Name);
    foreach (var directory in directoryInfo.GetDirectories())
    {
        //Statustext = directory.FullName;
        directoryNode.Nodes.Add(CreateDirectoryNode(directory));
    }
    foreach (var file in directoryInfo.GetFiles())
    directoryNode.Nodes.Add(new TreeNode(file.Name));
    return directoryNode;
}

public delegate void AddCDAnode(DirectoryInfo dirinfo);

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    DirectoryInfo dir = new DirectoryInfo(@"\\server\trabajos 2013\");
    Addnode(dir);
}

private void Form1_Load(object sender, EventArgs e)
{
    //Start filling the TreeView on a separate thread
    backgroundWorker1.RunWorkerAsync();
}

In full source code you will see commented code - that is from example and working in background without any troubles. So i think the problem is with my code of scanning directories.

The solution is also available here, if you want to download it.

1

There are 1 best solutions below

13
On

The problem is that you start a background thread, but then immediately go and call Invoke to run basically all of your real code in the UI thread, consequently the UI thread is being blocked.

What you need to do is separate out your UI logic from your non-UI logic. Ensure that the non-UI logic is executed in the background thread, and that the UI logic is executed in the UI thread.

In this case, CreateDirectoryNode(path) is basically all of your non-UI work. It's doing a whole bunch of file manipulation (which is time consuming) and in general creating the data that your UI will later use.

That should be done in the DoWork event of your background worker. Then you can set the Result property of the BGW based on the results it generated so that it can be used later.

For the UI portion, which is the treeView1.Nodes.Add( call, that should be in the RunWorkerCompleted event. That event is designed for you to manipulate the UI based on the results of the long running task. There you can read in the Result property of the BGW (it is a property in the arguments passed to the event handler) and there it can add the data to the tree view. Since this is in the UI thread you won't get cross thread exceptions, and since your long running file IO is done in the background thread it won't hand the UI.

So all you need is your CreateDirectryNode method and the following:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    DirectoryInfo dir = new DirectoryInfo(@"\\server\trabajos 2013\");
    e.Result = CreateDirectoryNode(dir);
}

//TODO ensure that this event handler is added to your BGW so it actually fires
void Form1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    treeView1.Nodes.Add((TreeNode)e.Result);
}