8

良い一日!

この件に関して、ご提案をお願いします。

「製品階層データ」をツリービューで表示するための小さなツールをオフィスで作成しています。私たちのアプリケーションはそれを表形式でしか表示できないため、階層内に誤ったデータがあるかどうかを追跡することは困難です。

いくつかのロジックを作成し、データを正しい階層で表示することができました。

しかし、ここでの私の主な問題は、100K〜200K以上のレコードを処理していることであり、各ノードを作成/割り当ててツリーに追加するには、間違いなく時間がかかります。私のテストでは、1分あたりに作成できるノードの平均は8000です。また、このアプリケーションの実行に伴い、このアプリケーションのメモリ使用量が徐々に増加することにも気づきました。

データの構造のスクリーンショットと、アプリケーションがどのように見えるかを示して、いくつかのアイデアを提供します。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

以下の私のコードを検討してください。これを最適化する方法についてのあなたの考えを知ってとてもうれしく思います。ここで改善すべきことがたくさんあることを私は知っています。

そして長い投稿でごめんなさい...

ちなみに、私はC#と.net2.0を使用しています。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Data;
using System.IO;
using System.Threading;

namespace WinformAppTest
{
    public partial class MainForm : Form
    {
        private DataSet _ds = new DataSet();

        public MainForm()
        {
            InitializeComponent();
        }

        void MainFormLoad(object sender, EventArgs e)
        {
            PopulateDataSet();

            lblTotalRows.Text = _ds.Tables[0].Rows.Count.ToString();
        }

        void PopulateDataSet()
        {
            string query = @"select * from " + "test.csv";
            try
            {
                OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\\;Extended Properties=\"Text;HDR=Yes;FMT=Delimited\"");
                OleDbDataAdapter da = new OleDbDataAdapter();

                OleDbCommand cmd = new OleDbCommand(query, conn);
                conn.Open();
                da.SelectCommand = cmd;
                _ds.Clear();
                da.Fill(_ds, "CSV");

                conn.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetBaseException().ToString());
            }
        }

        void BtnRunClick(object sender, EventArgs e)
        {
            Thread newThread1 = new Thread(MainForm.DoWork);
            newThread1.Start(this);
        }

        public static void DoWork(object data)
        {
            MainForm form = (MainForm)data;
            int counter = 0;
            TreeNode[] nd;

            foreach(DataRow row in ((MainForm)data)._ds.Tables[0].Rows)
            {
                TreeNode node = new TreeNode();
                if(row["Level Number"].ToString() == "1")
                {           
                    node.Name = row["ECC Hierarchy Code"].ToString();
                    node.Text = row["ECC Hierarchy Code"].ToString() + ", " + row["Name"].ToString();

                    form.Invoke((MethodInvoker)delegate { ((MainForm)data).treeView1.Nodes.Add(node); });       
                }
                else
                {                   
                    nd = ((MainForm)data).treeView1.Nodes.Find(row["Parent Code"].ToString(), true);
                    node.Name = (string)row["ECC Hierarchy Code"];
                    node.Text = row["ECC Hierarchy Code"].ToString() + ", " + row["Name"].ToString();

                    form.Invoke((MethodInvoker)delegate { nd[0].Nodes.Add(node); });
                }

                counter++;
                form.Invoke((MethodInvoker)delegate { ((MainForm)data).lblLoded.Text = counter.ToString(); });
            }       
        }
    }
}
4

3 に答える 3

9

その鍵は次のようなものかもしれません。

  1. TreeView.BeginUpdate を呼び出します
  2. TreeView に複数のノードを追加/削除する
  3. TreeView.EndUpdate を呼び出す

これにより、ノードの追加/削除中に発生するすべてのペイントが停止します。EndUpdate が呼び出されると、TreeView 全体が一度だけ描画されます。

http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.beginupdate.aspx

于 2012-06-03T23:04:16.190 に答える
3

いくつかのアイデア...

  1. スレッドを使用してデータを取得し、Invoke を使用して各データ項目をツリーに追加します。これは非常に遅いです。スレッドを使用して必要なすべてのデータを取得し、treeView1.Nodes.AddRange() を使用して一度にすべてのノードをツリーに追加することをお勧めします。

  2. アプリケーションを作り直して、ノードの最初のレベルのすべてのデータを取得し、ユーザーがツリー ノードを展開したときに下位レベルのノードのデータのみを取得することで、さらに最適化することができます。

于 2012-06-01T20:02:30.873 に答える
2

大規模なデータ セットを処理する場合、組み込みの WinForms コントロールは制限されます。私が思い出す限り、組み込みの TreeView はノードごとに独自のメモリを割り当てようとします (つまり、100K 以上のレコードのそれぞれに、データのコピーと追加のメタデータがあることを意味します。特定のセッションで表示されます。

私は、仮想ノードを提供するオープン ソースの TreeView の代替手段を使用して大きな成功を収めました (それらが表示されるまでレンダリングしません)。

http://www.codeproject.com/Articles/20552/Virtual-Treeview-Implementation

于 2012-06-01T04:04:56.933 に答える