简体   繁体   中英

C# TreeView populating from XML very slow - How to get it faster?

How to populate TreeView from XML faster, when i trying to load ~1MB XML file app is freezing. I know i need to do this in new Thread but when im trying to implemet this even small files cannot load. Please help.

private void populateTreeview()
{
    try
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.Load(XmlFilePath);
        treeView1.Nodes.Clear();
        treeView1.Nodes.Add(new TreeNode(xDoc.DocumentElement.Name));
        TreeNode tNode = new TreeNode();
        tNode = treeView1.Nodes[0];

        addTreeNode(xDoc.DocumentElement, tNode);
    }

    catch (Exception ex){ MessageBox.Show(ex.Message); }
}

public void addTreeNode(XmlNode xmlNode, TreeNode treeNode)
{    
    XmlNode xNode;
    TreeNode tNode;
    XmlNodeList xNodeList;

    if (xmlNode.HasChildNodes)
    {
        xNodeList = xmlNode.ChildNodes;
        for (int x = 0; x <= xNodeList.Count - 1; x++)
        {
            xNode = xmlNode.ChildNodes[x];
            treeNode.Nodes.Add(new TreeNode(xNode.Name));
            tNode = treeNode.Nodes[x];
            addTreeNode(xNode, tNode);
        }
    }

    else               
        treeNode.Text = xmlNode.OuterXml.Trim();
}

This is how i was trying to get it faster calling function from Task:

    public void addTreeNode(XmlNode xmlNode, TreeNode treeNode)
{    
    XmlNode xNode;
    TreeNode tNode;
    XmlNodeList xNodeList;
    if (xmlNode.HasChildNodes)
    {
        xNodeList = xmlNode.ChildNodes;
        for (int x = 0; x <= xNodeList.Count - 1; x++)
        {
            xNode = xmlNode.ChildNodes[x];
            treeNode.Nodes.Add(new TreeNode(xNode.Name));
            tNode = treeNode.Nodes[x];

            Task t = Task.Run(() => {
                BeginInvoke((System.Action)(() =>
                {
                    addTreeNode(xNode, tNode);
                }));
            });

            t.Wait();
        }
    }
    else {
                treeNode.Text = xmlNode.OuterXml.Trim();
    }

}

What I would do is to add a BeginUpdate() and EndUpdate() calls inside the populateTreeView() method. These calls disable/enable the redrawing of the TreeView for each change in it. As such the method would become:

private void populateTreeview()
{
    treeView1.BeginUpdate();
    try
    {
        ...
    }

    catch (Exception ex){ MessageBox.Show(ex.Message); }

    treeView1.EndUpdate();
}

other than that I wouldn't try to use any kind of Task inside the addTreeNode() method. Keep in mind that you can not update UI controls from a different thread other than the main tread and as such you you will have to do Invoke operations like trevView1.Invoke(...); which doesn't have a lot of meaning. Calling a method with Invoke will try to call that method from the thread that owns the control (in our case the TreeView). As such most of your update code will operate on the main thread rather on the tread expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM