3

我正在创建一个小工具,该工具将包含 XML 的树形视图。处理具有小文件大小的 XML 文件没有问题,但是当我尝试加载大型 XML 文件(大小为 21MB)时,我的应用程序变得无响应并且需要花费太多时间来加载 XML,而且大多数时候它没有根本不加载 XML。是否有任何修复或调整以使以下代码更快?

public TreeView(string filename)
        {
            InitializeComponent();

            this.Text = filename;

            XmlDataDocument xmldoc = new XmlDataDocument();
            XmlNode xmlnode;
            FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
            xmldoc.Load(fs);
            xmlnode = xmldoc.ChildNodes[1];
            treeView1.Nodes.Clear();
            treeView1.Nodes.Add(new TreeNode(xmldoc.DocumentElement.Name));
            TreeNode tNode;
            tNode = treeView1.Nodes[0];
            AddNode(xmlnode, tNode);
        }

        private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
        {
            XmlNode xNode;
            TreeNode tNode;
            XmlNodeList nodeList;
            int i = 0;
            if (inXmlNode.HasChildNodes)
            {
                nodeList = inXmlNode.ChildNodes;
                for (i = 0; i <= nodeList.Count - 1; i++)
                {
                    xNode = inXmlNode.ChildNodes[i];
                    inTreeNode.Nodes.Add(new TreeNode(xNode.Name));
                    tNode = inTreeNode.Nodes[i];
                    AddNode(xNode, tNode);
                }
            }
            else
            {
                inTreeNode.Text = inXmlNode.InnerText.ToString();
            }
        }
4

6 回答 6

2

您必须将加载部分与构建 TreeView 分开。

然后可以在后台线程 (BackgroundWorker) 上进行加载。

与 TreeView 相关的一切都必须发生在主线程上,但您可以使用 SuspendLayout 等加速它。

于 2013-01-15T15:39:37.103 回答
1

您可以尝试对子节点使用 Parallel.ForEach 来跨核心拆分事物。不过,这将很难实现。

http://msdn.microsoft.com/en-us/library/dd991486.aspx

于 2013-01-15T15:39:58.890 回答
1

对于无响应的部分,您可以将xml异步加载到BackgroundWorker中,也许构建树视图结构的整个过程都可以这样完成,并在完成后加载到控件本身中。

这可能不会大大提高速度,但它会保持 UI 响应。请记住,您不能直接从 BackgroundWorker 中运行的代码访问 UI,您必须通过 Dispatcher 调用它,如下所示:

this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
     // Execute code that works with UI controls
}));
于 2013-01-15T15:39:48.243 回答
0

首先,在处理大文件时,您应该真正切换到类似 SAX 的方法。请参阅在 C# 代码中解析(大)XML 的最佳方法是什么?一种可能的解决方案。

现在,您有一种可靠的方法来读取文件,无论文件有多大,都不会导致系统崩溃。

下一步是填充您的树视图,如前所述,您需要在单独的线程中执行此操作,我建议使用后台工作人员,因为它们非常易于使用。

至于在发生更改时更新 UI,我不熟悉 winforms,但如果它支持ObservableCollection,我建议使用 thou。

于 2013-01-15T17:44:19.243 回答
0

不要使用XmlDataDocument,而是更改要使用的代码,XmlReader因为此类在处理 XML 文件时提供了最高性能。XmlReader 是一个抽象类,可以从文件或任何其他数据流中读取。从文件中读取时,您不会一次加载整个文档。

更多信息在这里:shanselman 或这里的快速概述性能:LINQ to XML vs XmlDocument vs XmlReader

于 2013-01-15T15:49:49.023 回答
0

两个小建议:不要添加节点然后查找它,而是在临时变量中创建它,然后从那里使用它。您可以使用foreach循环而不是for循环。

代替

nodeList = inXmlNode.ChildNodes;
for (i = 0; i <= nodeList.Count - 1; i++)
{
    xNode = inXmlNode.ChildNodes[i];
    inTreeNode.Nodes.Add(new TreeNode(xNode.Name));
    tNode = inTreeNode.Nodes[i];
    AddNode(xNode, tNode);
}

foreach (var node in inXmlNode.ChildNodes)
{
    tNode = new TreeNode(node.Name);
    inTreeNode.Nodes.Add(tNode);
    AddNode(node, tNode);
}

我怀疑它会产生很大的不同,但它可能会有所帮助。

于 2013-01-15T15:44:48.903 回答