2012-05-08 23 views
3

外部システムから受信したデータを表示する必要があるアプリケーションを構築しています。このデータは非常に早く到着することができ、一方、各行が占めるバイト数は比較的少ない。つまり、時間単位ごとに多くの行を追加する必要があります。私は現在、自分のメモリ使用量が上がっていることを意味することができるよりも速くデータを受け取っているように見えています。DataGridViewのパフォーマンスとBindingListデータソースの組み合わせ

私は実際のdataGridViewを描画することと関係があると思います。私はdataGridViewをあまり微調整していないので、すでにパフォーマンスが向上しているはずです。 (自動サイズや特殊スタイルなどを無効にするなど)

最近追加されたばかりの行の色付けが追加されました。次のように現在、私のアプリケーションは動作します:

  1. 私は外部のシステム
  2. からデータを受信し、私は別のスレッドは、そのキューからデータを取得し、それを処理し、スレッド
  3. によってキュー(ConcurrencyQueue)にデータを配置しますテーブルにバインドされているBindingListに追加します。

追加実際には2つのパラメータ持つ関数で起こる: 1列のアイテムを含むリスト(アイテム) 2行の色(カラー)

見た目(半擬似)次のように

/* Store the color for the row in the color list so it is accessible from the event */ 

rowColors.Add(rowColor); //Class variable that stored the colors of the rows used in the DataGridCellFormatting event 

/* Create the row that is to be added. */ 
ResultRow resultRow = new ResultRow(); 

foreach(item in items) 
{ 
    resultRow.Set(item); /* It's actually a dictionary because some fields are optional, hence this instead of a  direct constructor call) */ 
} 

bindingList.Add(resultRow); 

/* Row coloring based on error is done in the OnCellFormatting() */ 


/* Auto scroll down */ 
if (dataGrid.Rows.Count > 0) 
{ 
    dataGrid.FirstDisplayedScrollingRowIndex = dataGrid.Rows.Count - 1; 
} 

iは受信色上記のコードに見られるように、以下のようにのDataGridViewの場合に使用されるリストに追加される:

void DataGridCellFormattingEvent(object sender, DataGridViewCellFormattingEventArgs e) 
{ 
    // done by column so it happens once per row 
    if (e.ColumnIndex == dataGrid.Columns["Errors"].Index) 
    { 
     dataGrid.Rows[e.RowIndex].DefaultCellStyle.BackColor = rowColors[e.RowIndex]; 
} 
} 

BindingListは次のように定義されています。

BindingList bindingList; ResultRowは、このような構造を持つクラスです

public class ResultRow 
{ 
    private int first = 0; 
    private string second = ""; 
    private UInt64 third = 0; 
    private IPAddress fourth = null; 
    //etc 

    public ResultRow() 
    { 
    } 

    public void Set (<the values>) //In actuallity a KeyValuePair 
    { 
     //field gets set here 
    } 

    public UInt64 Third 
    { 
     get { return third; } 
     set { third = value; } 
    } 

    /* etc. */ 

は、私はパフォーマンスを向上させるために行うことができます任意の比較的単純なものはありますか?私はおそらく処理中にデータグリッドの描画を無効にすることを考えていました。 (ただし、好ましくはありません)別のことは、受信したアイテムごとにではなく、更新頻度が低い可能性があります。 (何かが追加されたときにBindingListが自動的にDataGridViewを更新するようです)

誰かが喜んで助けてくれることを願っています。

-edit-

形式の応答ので、非常に悪いだけでなく、それは特にいくつかの時間後に、上記の方法でデータを処理していたとき。 (上記のプロセスはバックグラウンドワーカーとバックグラウンドスレッドで行われますが)

答えて

0

はい、速度を上げるためにできることがいくつかあります。

まず、データグリッドを仮想化します。これは、winformsデータグリッドへの組み込みのメカニズムであり、行を移入し、表示されているデータ項目のクライアント領域をペイントするだけです。したがって、コントロールが20行しか表示されていない場合(スクロールバーが他のものの場合)、20項目だけが実際にUIとしてデータグリッドに処理されます。 次に、グリッドをスクロールして他のアイテムを表示すると、データグリッドが要求に応じて要求された行を入力して表示します。 これに対して行う必要のある微妙な変更があります(CellValueNeededイベントを購読する必要があります)、バインディングソースのデータ項目を編集する必要があります。 詳細については、http://msdn.microsoft.com/en-us/library/ms171622.aspxを参照してください。

もう1つは、データの「チャンク(chunk)」に入力している間に、UIの更新を中断することです。 すでに述べたように、bindinglistは項目を追加するとグリッドを自動的に更新します。しかし、UIの更新を中断して一定間隔(毎秒)で再度有効にすることで、一定の割合でデータをストリーミングすることになります。 ただし、データに対して同じ処理を実行する必要があるため、データが完全に解決されるとは限りません。また、画面のちらつきを減らすのに効果的かもしれません。 詳細については、Control.SuspendLayout()およびControl.ResumeLayout()を参照してください。

私の考えでは、非常に大きなデータセットのグリッド機能を向上させることが唯一の目的であるため、仮想化は最も効果的なツールになります。

+0

私はデータグリッドにサスペンド/レジューム機構を適用しました。最初はあまり役に立たなかった。私はかなり長い間隔でDataGridを更新する新しいバックグラウンド作業者を作成しました。 (しかし、もっと多くのスレッドや呼び出しがありますが、これが良いことなのかどうかはわかりません。)実際にデータを読み込む前に、実際にその記事を読み込んでいたので、かなり複雑に思えました。この例はデータベースベースなので、直接適用することはできません。しかし、私はパフォーマンスのさらなる向上のためにそれを理解しようとしなければならないと思う。 – Arnold4107176

+0

喜んで助けてください。 msdnチュートリアルが常に最も役に立つとは限りません。 http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualModeは優れたリソースであり、これまでにないベストプラクティスの記事がレイアウトされていますが、正しい情報が含まれている必要があります。仮想化は比較的簡単です。CellValueNeededを使用してデータオブジェクトのプロパティをグリッドに提供する努力を怠ると、すぐに起動して実行できます。 –

+0

それはかなり理解できるようです。私はそれが動作するようにいくつかの情報が不足している記事を感じる。私は現時点でそれを実装しましたが、私のDataGridは空のままです。私はここに私の問題の詳細を掲載している:http://stackoverflow.com/questions/10512981/datagridview-virtual-mode-with-a-simple-list-as-a-source – Arnold4107176

3

グリッド内の単なる行数のため、しばらくするとパフォーマンスが低下することがあります。あなたはVirtual Modeを試してみてください。

まず、グリッドの更新を延期し、バッチで新しいエントリを追加してください。つまり、更新頻度を減らしてください。そのため、各バッチ更新前:

// stop raising update events 
bindingList.RaiseListChangedEvents = false; 

、その後:

// restore update events, raise reset event 
bindingList.RaiseListChangedEvents = true; 
bindingList.ResetBindings() 

最後の行の後に最後の行にスクロールし続けていきます。

関連する問題