【问题标题】:Tree view is not updating in background树视图未在后台更新
【发布时间】:2013-09-11 19:14:28
【问题描述】:

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

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,如果你想下载它。

【问题讨论】:

  • 那看起来不像源代码...
  • 很长,所以我把它贴到 Paste Bin ,你可以在我的消息末尾看到链接。请从问题中删除“减号”并阅读整篇文章。谢谢。
  • wetransfer.com/downloads/… - 这是在 goo.gl 中编码的链接 :)
  • @Oleg.Budeanu 您不应该只是提供大量代码转储并说“修复它”。如果您的代码太多以至于无法将其放入问题中,那么这表明您的代码太多了;您应该努力确定什么是相关的和不相关的,以便您可以包含足够的代码来演示问题,但不包括与问题无关的代码。做一些测试,看看哪些工作正常,哪些工作不能正常工作,以缩小可能不能工作的范围。
  • @Oleg.Budeanu 这就是我帮助你完成它的原因。您刚刚获得了很好的学习体验,可以在以后提出问题时使用它来帮助您,此外还可以将此问题改进到可以回答的程度。

标签: c# treeview backgroundworker directoryinfo


【解决方案1】:

问题是您启动了一个后台线程,然后立即去调用Invoke 以在 UI 线程中运行您的所有真实代码,因此 UI 线程被阻塞。

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

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

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

对于 UI 部分,即 treeView1.Nodes.Add( 调用,应该在 RunWorkerCompleted 事件中。该事件旨在让您根据长时间运行的任务的结果来操作 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);
}

【讨论】:

  • 这个解释很好,但重点是在扫描项目时将它们一一添加到 TreeView。这就是为什么我使用调用方法来访问 TreeView 并一一添加节点。但我理解你在那里描述的内容,并将尝试根据我的需要来实现。感谢您的帮助。
  • @Oleg.Budeanu 这是您问题中要包含的重要信息;这完全改变了您处理此类问题的方式。
  • 我在那儿说过..“我正在使用后台工作程序(线程类也是如此)在后台执行此操作,同时使用节点一一更新树视图。”对不起,这不是很明显..
  • 我唯一想到的就是将“addnode”方法放在BW的progresschange中。
  • @Oleg.Budeanu 这是组织它的一种方式,尽管它比这更复杂一些。您仍然需要确保您的长时间运行的任务在后台线程中运行,然后您可以让它使用应该添加的新节点更新进度,然后在进度更改处理程序中实际添加该节点。跨度>
猜你喜欢
  • 2019-02-27
  • 1970-01-01
  • 2010-09-30
  • 2011-10-23
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多