プロパティをtrueに設定したwinformsTreeView
コントロールがあります。また、プロパティにインスタンスを割り当てて、デフォルトのソーターをオーバーライドします。Sorted
IComparer
TreeViewNodeSorter
残念ながら、この関数を使用して数千のノードを追加するには、AddRange
おそらく10秒かかります。Sorted
falseに設定すると、AddRange
関数は1/2秒未満になります。(非常に多くのノードを追加することの有効性については議論しないでください)
ああ、あなたが言うのを聞きます..私のIComparer
オブジェクトに問題があります。プロファイラーによるとではありません。ソートオブジェクトに費やされる時間はほとんどありませんが、そのAddRange
関数は低速関数のリストの一番上にあります。
この問題は、テストプロジェクトで簡単に再現できます。のリストを作成し、関数TreeNode
を使用して既存の拡張ツリーノードに追加するだけです。AddRange
これにより、ツリーテキストのデフォルトの並べ替えが使用されます。これも不釣り合いに遅いです。
Sorted
テストprobjectでプロパティを無効にしList<T>.Sort
、ノードをツリーに追加する前にノードのリストで関数(ノードのテキストを比較するデリゲートを使用)を使用すると、どれほど遅くなるかを示すために、実質的に遅延はありません。
これは、を使用する前にノードを手動でソートする回避策につながりAddRange
ます。Sorted
それは問題ありませんが、既存の子ノードのセットにノードを追加するときに正しい挿入ポイントを見つけるには多くの作業が必要になります。単にtrueに設定するよりも便利ではありません。
とにかく行動をスピードアップする方法はありますか?
編集-追加する前にソートするのが唯一の方法のようです..少し面倒ですが、私は次の拡張メソッドを思いつきました:
public static void AddSortedRange(this TreeNodeCollection existingNodes, IList<TreeNode> nodes, TreeView treeView, IComparer sorter)
{
TreeNode[] array = new TreeNode[nodes.Count + existingNodes.Count];
existingNodes.CopyTo(array, 0);
nodes.CopyTo(array, existingNodes.Count);
Array.Sort(array, sorter);
treeView.BeginUpdate();
existingNodes.Clear();
existingNodes.AddRange(array);
treeView.EndUpdate();
}
既存のノードを配列にコピーし、新しいノードを追加し、配列を並べ替えてから、ツリービューでノードをインラインで操作しようとするものを置き換える方が高速です-上記のコードで最も遅い操作はexistingNodes.Clear()
呼び出しです