2012-05-08 3 views
3

Я создаю приложение, которое должно отображать данные, полученные от внешней системы. Эти данные могут быть очень быстрыми, а количество байтов, которое занимает каждая строка, относительно невелико. Это означает, что нужно добавить много строк за единицу времени. Я сейчас нахожусь в точке, где, кажется, я получаю данные быстрее, чем могу справиться с тем, что мое использование памяти растет.Производительность DataGridView в сочетании с источником данных BindingList

Я думаю, что большая часть этого связана с рисованием фактического dataGridView. Я сделал небольшие изменения в dataGridView в надежде, что это увеличит производительность уже. (например, отключить автоматический размер, специальные стили и т. д.)

В недавнем добавлении я добавил раскраску строк, что было необходимо. В настоящее время мое приложение работает следующим образом:

  1. Я получаю данные из внешней системы
  2. I место данных в очереди (ConcurrencyQueue) по теме
  3. Другого поток получает данные из этой очереди, обрабатывает его и добавляет его в 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. */ 

Есть ли относительно простых вещей, которые я могу сделать, чтобы увеличить производительность? Я думал о возможности отключения чертежа datagrid, когда обработка занята и рисуется, когда это будет сделано. (хотя и не рекомендуется). Другое дело, возможно, обновление менее часто, а не после каждого полученного элемента. (BindingList, кажется, автоматически обновляет DataGridView, когда что-то добавляется к нему, хотя)

Я надеюсь, что кто-то захочет или сможет помочь.

-edit-

Отзывчивость формы, потому что очень плохо, а когда он обрабатывает данные в способе, описанном выше, особенно после того, как некоторое время. (хотя вышеупомянутый процесс имеет место в фоновых работниках и фоновых потоках)

ответ

0

Да, есть несколько вещей, которые вы могли бы сделать, чтобы ускорить его.

Во-первых - виртуализируйте datagrid. Это встроенный механизм для datagrid winforms, который будет заполнять только строки и рисовать область клиента для видимых данных.Поэтому, если ваш элемент управления показывает только 20 строк (и полосу прокрутки для остальных), тогда только 20 элементов фактически обрабатываются в datagrid в качестве пользовательского интерфейса. Затем, когда вы просматриваете сетку для просмотра других элементов, набор данных заполняет и показывает запрошенные строки по требованию. . Вам нужно немного поработать над этим (события CellValueNeeded должны быть подписаны), и вам, возможно, потребуется отредактировать данные для данных bindingsource. Для получения дополнительной информации см. http://msdn.microsoft.com/en-us/library/ms171622.aspx.

Вторая вещь, которую вы можете сделать, - приостановить обновление пользовательского интерфейса, пока вы заполняете «кусок» ваших данных. Как вы уже указали, список привязок автоматически обновит сетку, когда вы добавляете в нее элементы. Но, приостанавливая обновление пользовательского интерфейса, затем повторно подключаясь через определенный интервал (скажем, каждую секунду), вы будете передавать потоки данных с меньшей скоростью. Обратите внимание, что для данных все равно необходимо выполнить ту же обработку, поэтому маловероятно, что это полностью решит ваши данные и может быть более эффективным при уменьшении мерцания экрана. Для получения дополнительной информации см. 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() 

После последней строки вести с прокруткой до последней строки.

Смежные вопросы