树视图不在后台更新

时间:2013-09-11 19:14:28

标签: c# treeview backgroundworker directoryinfo

这里是完整的源代码:http://pastebin.com/mLaGwwi0 正如您将注意到的,事情是扫描目录和文件并在树视图中填充它们。我正在使用后台工作程序(与Threads类相同)在后台执行此操作,同时逐个更新带有节点的treeview。 问题是它不在后台工作而不更新树视图。这是悬挂形式的代码的一部分:

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();
}

在完整源代码中,您将看到注释代码 - 这是来自示例并在后台工作而没有任何麻烦。所以我认为问题在于我的扫描目录代码。

解决方案是also available here,如果您想下载它。

1 个答案:

答案 0 :(得分:2)

问题是你启动了一个后台线程,然后立即调用Invoke来运行UI线程中的所有实际代码,从而阻止了UI线程。

您需要做的是将UI逻辑与非UI逻辑分开。确保在后台线程中执行非UI逻辑,并在UI线程中执行UI逻辑。

在这种情况下,CreateDirectoryNode(path)基本上都是您的非UI工作。它正在进行大量的文件操作(这非常耗时),并且通常会创建UI稍后将使用的数据。

应该在后台工作人员的DoWork事件中完成。然后,您可以根据BGW生成的结果设置BGW的Result属性,以便以后使用。

对于应在treeView1.Nodes.Add(事件中的RunWorkerCompleted调用的UI部分。该事件旨在让您根据长时间运行的任务的结果来操作UI。在那里,您可以读取BGW的Result属性(它是传递给事件处理程序的参数中的属性),并且可以将数据添加到树视图中。由于这是在UI线程中,因此您不会获得跨线程异常,并且由于您在后台线程中完成了长时间运行的文件IO,因此它不会处理UI。

所以你需要的只是你的CreateDirectryNode方法和以下内容:

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);
}