具有大量数据负载的Datagridview虚拟模式

时间:2011-04-21 12:32:08

标签: c# winforms multithreading datagridview

我想在虚拟模式下在datagridview中显示“大量繁重的数据”。

我使用缓冲区存储n(2)页数据,最初2个第一页存储在缓冲区中。当gridview滚动到缓冲区中不存在的行时,我加载当前的新页面并将其与旧页面交换。

为了模拟从数据库加载大量数据到缓冲区,我添加了这一行:   System.Threading.Thread.Sleep(3000);
结果,随着缓冲区更新本身,网格在这段时间内被冻结。

现在,正如我所知,添加一个线程在这里没有帮助,因为只有当滚动到达无缓冲行时才会发生一次操作。

  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);

并在表单事件处理程序中设置图像的可见属性,但结果不符合预期,我想睡眠发生在事件处理之前,因此图像在睡眠之前没有出现。

索姆,我想还需要一个胎面。但无法确定它什么时候开始,它应该做什么?

更新

我厌倦了建议的后台工作人员:
在由CellValueNeeded事件调用的方法内部,我检查所请求的行是否被缓冲,如果不是,我启动后台工作。

 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第二次完成它的工作时)!

1 个答案:

答案 0 :(得分:2)

当你到达一个无缓冲的行时,调用你的代码在第二个线程中获取所需的数据(新线程,线程池,后台工作者......选择一个)

此异步操作启动后,使“loading ...”控件可见

(此处您可能希望在操作完成之前禁用部分UI)

现在返回一个空字符串或其他一些虚拟值......

你的异步操作应该获得所需的数据然后调用ui线程的另一个方法(在你的Form的对象上调用Invoke(...))

需要调用调用以避免跨线程UI交互

在调用的方法中,您应该使用获取的数据来填充缓冲区,隐藏“loading ...”控件,使相应的行或单元格无效(datagridview具有执行此操作的方法)和最后但并非最不重要的是,如有必要,重新启用您的用户界面