“Streaming”结果来自BackgroundWorker的DataGridView

时间:2008-10-31 09:26:53

标签: datagridview backgroundworker

有没有办法将一组结果(例如,一个DataTable)从BackgroundWorker“流”到DataGridView。我想要做的是查询数据,并在DataGridView 中填充结果(如SQL Server Management Studio中的查询网格结果)。我的第一个想法是使用BackgroundWorker(以避免UI冻结效果),但是当BackgroundWorker加载结果时,仍然会有可感知的“滞后”。

最好的方法是什么?

4 个答案:

答案 0 :(得分:1)

你可以:

将DataGridView绑定到最初为空的DataTable。

然后,在您的工作线程中,使用线程安全集合(例如,同步队列)并调用Control.BeginInvoke将记录信息传递给UI线程。

在UI线程中,您将项目从队列中拉出并将相应的行添加到DataTable中。通过数据绑定的魔力,这些将被添加到gridview。

然而,通过使用多线程,您立即使您的程序更容易被破坏!我没有尝试过这个特定的方案,并且不知道在将项目添加到GridView时,GridView是否会被有效地渲染。我已经使用多线程填充了树视图,这确实是一个很酷的效果。但是,我最终禁用了该功能,因为它引入了错误,因为它不是完全正确的实现,处理所有可能的用户交互。

答案 1 :(得分:1)

已经尝试过,并完成了此操作。应用程序和体系结构是在我来公司之前完成的,我所做的就是“分页”和异步。

他们有一个已经在其中进行分页的存储过程...所以我做的是,在第一次请求时,发回总结果的“大小”(以及page1的数据)。

在客户端,我向DataTable添加了空白行...(空白,之外的“RowNumber”字段)。

在进一步的数据页面(收到异步)后,我会得到行[X],将它的“ItemArray”设置为新数组,然后更新我的网格。例如:

myDataGridView.Rows[rowNumber].SetValues(valuesFromNewPage);

答案 2 :(得分:1)

如果你只有一个可以修改底层集合的线程,那么效果会更好。我有一个只读的DGV,这样添加/删除行的唯一方法是操作底层的BindingSource。我有一个同步线程,定期添加/删除BindingSource中的项目。

我确实要做一件“棘手”的事情 - 如果要更新的项目是所选项目,你不能只说

myBindingSource[n] = newItem;

但您必须将新项目中的值深层复制到现有项目中。否则,您将触发“已更改”事件,该事件将重绘与数据源绑定的任何其他内容。当我完成参考副本时,我得到了明显的闪烁,并切换到深拷贝(仅适用于当前项目)修复它。

当然,如果您让用户直接从表单中修改数据,而不是将其用作只读视图,那么您将打开一个全新的(丑陋的!)蠕虫病毒。

答案 3 :(得分:0)

如果进程花费2秒或更短时间,那么我将显示“忙”光标并进行内联更新。这有两个原因:

  • 开始一项只需几秒钟的操作的人在操作完成时仍将处于“专注”思维模式。潜意识里,他仍然在等待他的行动结果,并且还没有将他的意识大脑从那个特定的焦点切换出来(只要应用程序显示“忙”信号)。

  • 鉴于上述情况,我不认为多线程的认知开销及其伴随的所有危险是值得的。

如果这个过程需要5秒钟,那么我会首先集中精力将其降低到2秒或更短。同样,通常更容易集中精力提高性能(例如,通过SQL中的分页)而不是引入多线程。即使使用 BackgroundWorker 类型,多线程中涉及的非顺序交互仍然难以分析并使其安全。

如果您发现没有办法将延迟减少到2秒或更短,那么您可以使用类似confuzatron推荐的技术。但即便如此,您可能仍希望向最终用户显示进度对话框,因为 将在超过2秒的等待后进行上下文切换。进度对话框让他可以轻松获取有关何时可以切换回专注于您的上下文的信息。