Управление Treeview - обходные пути ContextSwitchDeadlock - PullRequest
1 голос
/ 26 января 2010

Я построил древовидный элемент управления, который отображает структуру каталогов любого диска или папки. Однако, если вы выбираете диск или что-то с большой структурой папок и подпапок, загрузка элемента управления занимает много времени, и в некоторых случаях отображается сообщение 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;
    }

Спасибо, Р.

1 Ответ

4 голосов
/ 26 января 2010

Если вам не нужна вся структура, загруженная в 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);
...