2016-10-12 54 views
5

StackflowとC#newbie here!Treeviewへの文字列のリストの読み込みを高速化

私はいくつかのコードをツリービューコントロールに文字列のリストをロードし、それはうまく動作します。唯一の問題は速度です。リストが大きい場合、ロードに時間がかかりますが、UIをしばらくロックする以外は問題ありません。

C:\ DRIVERS \ test1.txtという
C:\ DRIVERS \ test2.txtという名前
C:

だから例は、このような文字列のリスト(しかし、はるかに大きい)だろう\ドライバ\フォルダ\ test1.txtという
C:\兄弟\テスター\ text1.zip
C:\弟\別の\ text2.zip
C:\データ\のCompany1のの\
C accounts.rar:\データ\のCompany2の\ accounts.rar

treeviewは、文字列をバックスラッシュマーカーで分割し、エクスプローラビューにきれいに配置します。これはいいです!

tvRestoreは、例のTreeviewコントロールです。

foreach (string path in lstKeys) 
     { 

      lastNode = null; 
      subPathAgg = string.Empty; 
      foreach (string subPath in path.Split(new string[] { "\\" }, StringSplitOptions.None)) 
      { 
       foreach (string item in subPath.Split(new string[] { "\\" }, StringSplitOptions.None)) 
       { 
        if (item == "" || item == null) 
        { 
         continue; 
        } 
        subPathAgg += item + "\\"; 

        TreeNode[] n = tvRestore.Nodes.Find(subPathAgg, true); 

        if (n.Length > 0) 
        { 
         lastNode = n[0]; 

         continue; 
        } 
        else 
        { 
         // lastNode = null; 
        } 

        TreeNode[] nodes = tvRestore.Nodes.Find(subPathAgg, true); 
        if (nodes.Length == 0) 
         if (lastNode == null) 
          lastNode = tvRestore.Nodes.Add(subPathAgg, item); 
         else 
          lastNode = lastNode.Nodes.Add(subPathAgg, item); 
        else 
         lastNode = nodes[0]; 
       } 
      } 
     } 

唯一の問題は速度です。コントロールが別のスレッドにあるため、スレッド例外を使用しようとしましたが、コード例外が発生しました。私はNodes.Addを呼び出す必要があると信じていますが、これを行う方法を理解することはできません。

理想的には、アプリケーションが起動したときにツリービューが表示されるようになりますが、大きなリストの場合は30〜40秒以上ロックアップしたくないという理想があります。

この処理を高速化する最も良い方法は何ですか?

+2

'treeView1.BeginUpdate();でノードを追加する前に描画をオフにしてから、' EndUpdate();で再び有効にしてください。 – LarsTech

答えて

3

これをバックグラウンドで実行するなど、いくつかのことができます。このためにTask.Run()を使用したいと思います。

private void Form1_Load(object sender, EventArgs e) 
{ 
    // Show the user something 
    treeView1.Nodes.Add("Loading..."); 
    // Run the tree load in the background 
    Task.Run(() => LoadTree()); 
} 

すべてのノードがあるまで、そして、あなたのタスクは、すべての新しいノードを含むツリーノードを構築し、範囲として新しいノードを追加するには、ツリービューを起動し、だけでなく、視覚的な更新を防止するためにBeginUpdateメソッド... EndUpdateメソッドを使用することができますロードされる。

private void LoadTree() 
{ 
    // Get a list of everything under the users' temp folder as an example 
    string[] fileList; 
    DirectoryInfo df = new DirectoryInfo(Path.GetTempPath()); 
    fileList = df.GetFiles("*.*",SearchOption.AllDirectories).Select<FileInfo, string>((f) => f.FullName).ToArray(); 

    // Parse the file list into a TreeNode collection 
    TreeNode node = GetNodes(new TreeNode(), fileList); 

    // Copy the new nodes to an array 
    int nodeCount = node.Nodes.Count; 
    TreeNode[] nodes = new TreeNode[nodeCount]; 
    node.Nodes.CopyTo(nodes, 0); 

    // Invoke the treeview to add the nodes 
    treeView1.Invoke((Action)delegate() 
    { 
     treeView1.BeginUpdate(); // No visual updates until we say 
     treeView1.Nodes.Clear(); // Remove existing nodes 
     treeView1.Nodes.AddRange(nodes); // Add the new nodes 
     treeView1.EndUpdate(); // Allow the treeview to update visually 
    }); 
} 

これは、TreeNodesのリストを作成する方法です。

private TreeNode GetNodes(TreeNode parent, string[] fileList) 
{ 
    // build a TreeNode collection from the file list 
    foreach (string strPath in fileList) 
    { 
     // Every time we parse a new file path, we start at the top level again 
     TreeNode thisParent = parent; 

     // split the file path into pieces at every backslash 
     foreach (string pathPart in strPath.Split('\\')) 
     { 
      // check if we already have a node for this 
      TreeNode[] tn = thisParent.Nodes.Find(pathPart, false); 

      if (tn.Length == 0) 
      { 
       // no node found, so add one 
       thisParent = thisParent.Nodes.Add(pathPart,pathPart); 
      } 
      else 
      { 
       // we already have this node, so use it as the parent of the next part of the path 
       thisParent = tn[0]; 
      } 
     } 

    } 
    return parent; 
} 

私のマシンでは、この方法で56000ノードをツリービューにロードするのに約1.5秒かかり、UIはブロックされません。

関連する問題