开发者

Datagridview virtualmode with heavy data load

I want to display a "lot of heavy data" inside datagridview in virtual mode.

I use a buffer where I store n (2) pages of data, initially 2 first pages are stored in buffer. When the gridview is scrolled upto a row that does not exist in buffer i load the current new page and swap it with an old page.

To simulate loading heavy data from database into the buffer, I added this line: System.Threading.Thread.Sleep(3000);

as the result , as the buffer update itself the grid is frozen for this period of time.

Now, as I understand adding a thread won't help here because there is only 1 operation that happens only when scroll reaches unbuffered row.

  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

    }

So I am thinking about adding a "spinning wheel" animation above the gird when it happens.

I tried, to send event to form to show/hide the image within the method that updates the buffer:

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

System.Threading.Thread.Sleep(3000);

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

and on form event handler set the visible property of the image, but the result was not as expected, i guess Sleep happened before event was handled, so the image didn't appear before the sleep.

Som I guess that a tread is still needed. But can't figure when it sholud started and what should it do?

Update:

I tired the suggested background worker:

Inside the method that is beeing called by CellValueNeeded event, i check if the requested row is buffered, if not i start 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"; 

And this:

开发者_运维技巧
bgWorker.RunWorkerCompleted += (sender, e) =>
{
    if (IvalidateEvent != null)
        IvalidateEvent();  //send event to form, where invalidate the gridview  dataGridView1.Invalidate();
};            

it works but there a few problems with that: 1) I got many dummy results in my grid, even if it's not for long - I don't like it much. 2)it even takes more time if I just left it as is, probably because backgroundworker consumes some time and because I actually invalidate grid and call CellValueNeeded event 2 times (first onem to start backgroundworkerm second time when it finishes it's work)!


when you reach an unbuffered line, call your code to get the required data in a 2nd thread (new Thread, threadpool, backgroundworker ... choose one)

after this async operation has been started make the "loading..." control visible

(here you will probably want to disable parts of your UI until the operation is completed)

for now return an empty string or some other dummy value...

your async operation should get the desired data and then invoke another method the ui thread (call Invoke(...) on your Form's object)

the invoke call is needed to avoid cross-thread UI interaction

in the invoked method you should use the fetched data to populate your buffer, hide the "loading..." control, invalidate the corresponding row(s) or cell(s) (the datagridview has methods to do this) and last but not least reenable your UI if necessary

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜