2011-04-21 2 views
1

Я хочу отобразить «много тяжелых данных» внутри datagridview в виртуальном режиме.Виртуальный режим Datagridview с тяжелой нагрузкой

Я использую буфер, в котором храню n (2) страниц данных, изначально 2 первых страницы хранятся в буфере. Когда gridview прокручивается до строки, которая не существует в буфере, я загружаю текущую новую страницу и меняю ее на старую страницу.

Чтобы имитировать загрузку тяжелых данных из базы данных в буфер, я добавил эту строку: System.Threading.Thread.Sleep (3000);
В результате, поскольку обновление буфера само по себе сетка замораживается на этот период времени.

Теперь, поскольку я понимаю, что добавление нити не поможет здесь, потому что есть только 1 операция, которая происходит только тогда, когда свиток достигает небуферизованной строки.

private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e) 
    { 

     e.Value = theBuffer.ReturnFromBuffer(e.RowIndex, e.ColumnIndex); 
//I check there if row index is in buffer and if not i update the buffer with new page and return the value 

    } 

Так что я думаю о добавлении анимации «вращающегося колеса» над поясом, когда это произойдет.

Я пытался, чтобы отправить событие, чтобы сформировать, чтобы показать/скрыть изображение внутри метода, который обновляет буфер:

if (ProgressEvent != null) 
    ProgressEvent(true); 

System.Threading.Thread.Sleep(3000); 

if (ProgressEvent != null) 
    ProgressEvent(false); 

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

Сом, я думаю, что протектора по-прежнему необходимо. Но не может понять, когда он начался и что он должен делать?

Update:

Я устал предложенный фон работник:
Внутри метода, который вызывается неоспоримым CellValueNeeded событием, я чек, если запрашиваемая строка в буфер, если не я начать BackgroundWorker.

if (!bgWorker.IsBusy) //otherwise worker will be started for every column of the row 
{ 
     bgWorker.DoWork += (sender, e) => 
     { 
      UpdateBuffer(rowIndex);       
      }; 
     bgWorker.RunWorkerAsync(); 
} 
return "null"; 

И это:

bgWorker.RunWorkerCompleted += (sender, e) => 
{ 
    if (IvalidateEvent != null) 
     IvalidateEvent(); //send event to form, where invalidate the gridview dataGridView1.Invalidate(); 
};    

он работает, но есть несколько проблем с этим: 1) я получил много фиктивных результатов в моей сетке, даже если это не так долго - я не как много. 2) это даже занимает больше времени, если я просто оставил его как есть, возможно, потому, что работник фокуса потребляет некоторое время, и потому что я фактически недействителен сетью и вызываю событие CellValueNeeded 2 раза (сначала он снова запускает backgroundworkerm во второй раз, когда он заканчивает работу)!

+0

аннулирование всей сетки немного напоминает «перебор» ... это также перекрасит все ячейки, которые имеют правильные значения, а не только те, у которых есть соски. другой подход, чтобы избежать фиктивных значений при прокрутке через сетку, заключался бы в том, чтобы реагировать на прокрутку. попробуйте получить строки, близкие к отображаемым строкам, прежде чем они будут запрошены, в этом случае значения, вероятно, будут там до того, как CellNeedsValue запросит их – DarkSquirrel42

+0

@ DarkSquirrel42, CellNeedsValue буферизует не только нужную строку, но и ряд строк вперед. единственная проблема, когда мне нужно загружать новые строки. Я не против замораживания сетки, но анимация должна появляться так, как бывает. без фиктивных значений –

+0

, когда datagridview поднимает cellvalueneeded, вы можете указать значение, которое будет отображаться в ячейке. если у вас нет этого значения, вы не можете его указать. поэтому у вас есть 2 варианта: 1) либо предоставить «загрузку» -сообщения, либо ничего (пустую строку), заполнить свой буфер в асинхронной операции и когда данные будут готовы к обновлению ячейки. или вариант 2) синхронно заполнять буфер и возвращать требуемое значение. конечно, вариант 2 блокирует поток пользовательского интерфейса, поэтому никакая загрузка анимации, перерисовка формы или взаимодействие с пользователем не будут доступны (если вы не делаете плохие вещи, такие как Application.DoEvents - это будет больно отлаживать) – DarkSquirrel42

ответ

2

когда вы достигнете небуферизованных линии, вызовите свой код, чтобы получить необходимые данные в 2 нити (новый Thread, Threadpool, BackgroundWorker ... выбор)

после этой операции асинхронной было начато сделать " загрузка ...»контроль видимой

(здесь вы, вероятно, хотите, чтобы отключить части вашего UI, пока операция не будет завершена)

сейчас возвращает пустую строку или какое-либо другое фиктивное значение ...

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

вызов Invoke необходим, чтобы избежать взаимодействий UI кросса-нити

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

+0

да, я думал об этом, но есть проблема, что я попытаюсь объяснить: может быть ситуация, когда новые потоки загружаются в данные в буфер, пользователь может снова прокрутить сетку, и начнется новый поток! это вызовет много беспорядков. Я не думаю, что хочу заблокировать свиток. –

+0

А также, CellValueNeeded ждет его значения, как он может использовать поток? он не будет ждать завершения потока –

+0

1st: ожидающий обработчик cellValueNeeded ... не позволяйте ему ждать ... возвращает фиктивное значение, например. "Загрузка ...". и позже, когда операция async завершится и данные будут в вашем буфере, аннулируйте строку/ячейку. что снова вызовет CellValueNeeded, а затем вы сможете получить реальную ценность. 2nd: иметь только одного работника за один раз, когда вы можете написать класс, который обрабатывает запросы на данные. когда данные запрашиваются, и данные в настоящее время не получены, запустите поток. когда данные в настоящее время выбраны, в очереди запрос ... в конце процесса процесса получения запроса на запросы ожидания ... – DarkSquirrel42

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