アプリ版:「スタンプのみでお礼する」機能のリリースについて

C# TreeViewについて質問させてください。
ノード(子ノード含む)を数万件以上登録する際に、効率の良い方法を教えて頂けないでしょうか?

実際のコードとは異なりますが、大まかに以下のような処理をメインスレッドで行っています。
class MyTreeNode : TreeNode{
  void AddNode(){
    BeginUpdate();
    SuspendLayout();
    foreach( var 親ノード情報 in 親ノード情報リスト ){
      TreeNode parentNode = new TreeNode( 親ノード名 );
      foreach( var 子ノード情報 in 子ノード情報リスト ){
        TreeNode childNode = new TreeNode( 子ノード名);
        parentNode.Nodes.Add( childNode );
      }
      this.Nodes.Add( parentNode );
    }
    ResumeLayout();
    EndUpdate();
  }
}
この方法ですと、かなり時間がかかってしまい、UIが固まったようになってしまいます。

(TreeViewに、子ノードの一斉展開機能が必要なので、親ノード展開時のイベントを拾って
 子ノードを追加する方法は上記と同じく遅くなってしまうのではと思っていますがどうなんでしょうか?)

A 回答 (1件)

今試せる環境がないので半分くらい無責任発言なんですが、一応案として、何かの参考になれば。



・効率が良くなるかもしれない方法
 TreeNodeを配列化してAddRangeする(Addを使わず配列で渡す)
 ※配列はListではなくTreeNode[]でnew

・追加時間を短縮する方法
 System.Threading.Tasks.Parallelを使って並列実行する
 ぱっと見、1つの「親ノード情報」に対する子は予め決まってそうなので、「親ノード情報」単位で並列化が可能にみえます。ノード間で何かしら依存する場合はたぶん無理です。

・ノード追加処理を非同期化させるか、メッセージ処理をはさむ
 UIが固まるのは、処理が重いからというより、ウインドウが長時間メッセージを処理できなくなるからです。
 なので、たとえば何階層か展開する毎にメッセージ処理を挟めばUIが止まることはなくなります(処理中にウインドウが操作を受け付けるようになるので別の問題起き得ます)。
    • good
    • 0
この回答へのお礼

回答、ありがとうございます。
色々とバタバタして返信が遅くなってしまいました、すいません。

> TreeNodeを配列化してAddRangeする
この手法にて、約10万件追加されるときの時間が1秒以上改善されました。
大変たすかりました、ありがとうございます。

また、調査の結果、一番のネックになっているところが見つかりました。
(指摘頂いたコードを抜粋して質問させていただきましたが、そのあとの処理で親子ノード1個追加される度に、毎回Sortを実行していたので...)
試しに上記サンプルとSortを外して実行してみると、大きなストレスなく動作させることができました。

要望として、親ノードのソートはしたいですが、子ノードまでソートする必要はないと思われるので、ソート部分を自作して乗り切ろうと思います。

結局、質問した際のコードとは別のところが一番の原因で、大変申し訳ございません。
次はもう少し気をつけて質問します。

> System.Threading.Tasks.Parallelを使って並列実行する
> ノード追加処理を非同期化させるか、メッセージ処理をはさむ

上記2点についての案もありがとうございます。
私の今の力量では、期間内に両方検証し比較することができないので、後日時間があるときに、確認してみたいと思います。
(特にSystem.Threading.Tasks.Parallelは機能を確認してみると、できるとすごく便利そうです。)

複数の案とともに、処理改善もでき、一番の原因も判明いたしましたので、duke_kimuraさんをベストアンサーにさせていただき、この問題は解決済みにさせていただきたいと思います。
本当にありがとうございました。

お礼日時:2014/12/08 22:24

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!