3

小さなツールを作成しています。このツールには XML のツリービューが含まれます。ファイル サイズが小さい XML ファイルの処理には問題はありませんが、大きな XML ファイル (サイズが 21 MB) を読み込もうとすると、アプリケーションが応答しなくなり、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

応答しない部分については、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 に答える
1

子ノードに Parallel.ForEach を使用して、コア間で物事を分割することができます。ただし、これを実装するのは難しいでしょう。

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

于 2013-01-15T15:39:58.890 に答える
0

2 つの小さな提案: ノードを追加してから検索する代わりに、temp 変数でノードを作成し、そこから操作します。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 に答える
0

を使用する代わりに、使用XmlDataDocumentするコードを変更してくださいXmlReader。このクラスは、XML ファイルを操作するときに最高のパフォーマンスを提供します。XmlReader は、ファイルまたはその他のデータ ストリームから読み取ることができる抽象クラスです。ファイルから読み取る場合、ドキュメント全体を一度にロードするわけではありません。

詳細はこちら: shanselman による簡単な概要
またはこちらパフォーマンス: LINQ to XML vs XmlDocument vs XmlReader

于 2013-01-15T15:49:49.023 に答える
0

まず、大きなファイルを扱うときは、SAX のようなアプローチに切り替える必要があります。C# コードで (大きな) XML を解析する最良の方法は何ですか?を参照してください。1つの可能な解決策のために。

これで、ファイルのサイズに関係なく、システムをクラッシュさせずにファイルを読み取る確実な方法が得られました。

次のステップは、別のスレッドでこれを行う必要があると述べたように、ツリービューを埋めることです。バックグラウンドワーカーは非常に簡単に操作できるため、お勧めします。

変更が発生したときに UI を更新することに関しては、winforms には詳しくありませんが、ObservableCollectionをサポートしている場合は、thous を使用することをお勧めします。

于 2013-01-15T17:44:19.243 に答える