【问题标题】:Treeview Control - ContextSwitchDeadlock workarounds树视图控件 - ContextSwitchDeadlock 解决方法
【发布时间】:2010-01-26 06:28:05
【问题描述】:

我已经构建了一个树视图控件,它列出了任何驱动器或文件夹的目录结构。但是,如果您选择一个驱动器或具有大量文件夹和子文件夹结构的东西,则该控件需要很长时间才能加载,并且在某些情况下会显示 MDA ContextSwitchDeadlock 消息。我已经禁用了 MDA 死锁错误消息并且它可以工作,但我不喜欢时间因素和应用程序看起来像它已锁定。如何修改代码以使其不断发送消息,而不是缓冲整个视图并将其全部传递给控件,​​有没有办法在构建时将其推送到控件?

//Call line
treeView1.Nodes.Add(TraverseDirectory(source_computer_fldbrowser.SelectedPath));

private TreeNode TraverseDirectory(string path)
    {
        TreeNode result;
        try
        {
            string[] subdirs = Directory.GetDirectories(path);
            result = new TreeNode(path);
            foreach (string subdir in subdirs)
            {
                TreeNode child = TraverseDirectory(subdir);
                if (child != null) { result.Nodes.Add(child); }
            }
            return result;
        }
        catch (UnauthorizedAccessException)
        {
            // ignore dir
            result = null;
        }
        return result;
    }

谢谢R。

【问题讨论】:

  • 不要这样做,甚至不使用线程。一个大的驱动器很容易需要一分钟。 Alex 向您展示了 Windows 是如何做到这一点的,当用户展开一个节点时替换一个虚拟子节点,因此您只需要读取一个目录。

标签: c# visual-studio-2008 treeview controls


【解决方案1】:

如果您不需要在 TreeView 中加载整个结构,而只需要查看正在扩展的内容,则可以这样做:

// Handle the BeforeExpand event
private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
   if (e.Node.Tag != null) {
       AddTopDirectories(e.Node, (string)e.Node.Tag);
   }
}

private void AddTopDirectories(TreeNode node, string path)
{
    node.BeginUpdate(); // for best performance
    node.Nodes.Clear(); // clear dummy node if exists

    try {
        string[] subdirs = Directory.GetDirectories(path);

        foreach (string subdir in subdirs) {
            TreeNode child = new TreeNode(subdir);
            child.Tag = subdir; // save dir in tag

            // if have subdirs, add dummy node
            // to display the [+] allowing expansion
            if (Directory.GetDirectories(subdir).Length > 0) {
                child.Nodes.Add(new TreeNode()); 
            }
            node.Nodes.Add(child);
        }
    } catch (UnauthorizedAccessException) { // ignore dir
    } finally {
        node.EndUpdate(); // need to be called because we called BeginUpdate
        node.Tag = null; // clear tag
    }
}

调用线路将是:

TreeNode root = new TreeNode(source_computer_fldbrowser.SelectedPath);
AddTopDirectories(root, source_computer_fldbrowser.SelectedPath);
treeView1.Nodes.Add(root);

【讨论】:

  • @Alex: node.BeginUpdate() 和 node.EndUpdate() 不应该是 treeView1.BeginUpdate() 和 treeView1.EndUpdate() 吗? TreeNode 似乎没有这些方法...
猜你喜欢
  • 2011-11-03
  • 2010-12-09
  • 1970-01-01
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
相关资源
最近更新 更多