2012-05-08 37 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; 
} 

如在我接收被添加到其在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時,雖然有東西)

我希望有人願意/能夠幫助。

CNC中

形式的響應,因爲相當糟糕,以及當它在處理上述數據的方式,尤其是在一段時間後。 (即使上述過程發生在後臺工作程序和後臺線程中)

回答

0

是的,有幾件事情可以加快速度。

首先 - 虛擬化數據網格。這是一種內置於Winforms數據網格的機制,它只填充行併爲客戶區繪製可見的數據項。因此,如果你的控件只顯示20行(而其他的滾動條),那麼實際上只有20個項目被作爲UI處理到數據網格中。 然後,當您滾動網格查看其他項目時,數據網格按需填充並顯示請求的行。 您需要做一些修補(CellValueNeeded事件需要訂閱),您可能需要編輯綁定源數據項。 有關更多信息,請參閱http://msdn.microsoft.com/en-us/library/ms171622.aspx

您可以做的第二件事是在您填充數據的「塊」時暫停UI的更新。 正如您已經指出的那樣,當您添加項目時,綁定列表會自動更新網格。但通過暫停用戶界面的更新,然後以一定的時間間隔重新啓用(例如每秒),您將以較低的速率傳輸數據。 但請注意,數據仍需要進行相同的處理,因此這不太可能完全解決您的數據,並且可能會更有效地減少屏幕閃爍。 有關更多信息,請參閱Control.SuspendLayout()Control.ResumeLayout()

在我看來,虛擬化將是您最有效的工具,因爲它的唯一目的是改善非常大的數據集的網格功能。

+0

我已經在我的數據網格中應用了掛起/恢復機制。起初這並沒有太多幫助。我現在已經創建了一個新的後臺工作負責人,負責在相當大的時間間隔內更新數據網格,併爲這些數據網格提供幫助。 (但更多的線程和更多的調用,不知道這是否是一件好事..)我實際上碰到了剛剛在數據加載文章之前,它似乎很複雜,所以我希望不必這樣做。這個例子也是基於數據庫的,所以我不能直接應用它。但我想我將不得不試圖找出進一步提高性能的方法。 – Arnold4107176

+0

很高興幫助。毫無疑問,MSDN教程並不總是最有幫助的。 http://www.codeproject.com/Articles/23937/Paging-Data-with-DataGridView-in-VirtualMode是一個更好的資源,它不是有史以來最好的codeproject文章,但應包含正確的信息。虛擬化相對簡單,如果您努力通過CellValueNeeded爲網格提供數據對象屬性,那麼您將立即開始運行。 –

+0

這似乎很容易理解。我確實感覺這篇文章缺少一些信息,但是它能夠正常工作。我目前實現它,但我的數據網格保持空白。我在這裏發佈了我的問題的詳細信息: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() 

最後一行之後進行帶滾動到最後一行。