我想在虚拟模式下在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第二次完成它的工作时)!
答案 0 :(得分:2)
当你到达一个无缓冲的行时,调用你的代码在第二个线程中获取所需的数据(新线程,线程池,后台工作者......选择一个)
此异步操作启动后,使“loading ...”控件可见
(此处您可能希望在操作完成之前禁用部分UI)
现在返回一个空字符串或其他一些虚拟值......
你的异步操作应该获得所需的数据然后调用ui线程的另一个方法(在你的Form的对象上调用Invoke(...))
需要调用调用以避免跨线程UI交互
在调用的方法中,您应该使用获取的数据来填充缓冲区,隐藏“loading ...”控件,使相应的行或单元格无效(datagridview具有执行此操作的方法)和最后但并非最不重要的是,如有必要,重新启用您的用户界面