1

我有一个表单“StartForm”,用户在其中选择组合框,然后单击一个按钮。从那里我想:

  1. 生成另一个表单的实例,“MainForm”

  2. 在该表单上填充大约 50 000 行的 DataGridView

  3. 循环遍历数据网格视图中的每一行并对其执行一些处理。就我而言,它根据单元格的值格式化行颜色,并更新一些列。

  4. 显示表格。

这是直截了当的,但是由于大量的行和每一行的处理时间,UI 在构造 MainForm 时冻结。因此,我需要在后台线程上构建 MainForm,并在此过程中在 StartForm 上填充进度条。

使用 backgroundWorker 时,我不断收到跨线程异常或我的格式丢失,并且 control.Invoke() 似乎也抛出异常。也许我只是没有正确使用这些......

有人可以解释一下如何完成上述工作吗?我试图让问题保持基本理解,以便对其他人有所帮助,但如果您想要我的代码,请询问。

谢谢!

4

2 回答 2

2

我认为您需要为数据网格实现虚拟模式。查看有关在 DataGridView 控件中实现虚拟模式的msdn 文章。小样本:

grid.VirtualMode = true; // enable virtual mode
grid.RowCount = source.Count; // 50000
grid.CellValueNeeded += grid_CellValueNeeded;
grid.CellPainting += grid_CellPainting;

使用CellValueNeeded事件处理程序为单元格提供值(即从源中选择值)。使用CellPainting事件处理程序根据单元格值设置单元格颜色(使用e.CellStyle属性)。如果用数据填充源需要很长时间,您可以在 BackgroundWorker 中执行此操作。但是在虚拟模式下格式化和显示数据 - 这是最好的选择,当你有大量的行时(顺便说一句,考虑应用一些过滤 - 很少用户一次需要 50000 行数据)。

于 2012-12-17T11:27:20.240 回答
0

默认情况下,所有工作都在 UI 线程上完成,这会产生“崩溃”的错觉,因为在繁重的工作期间 UI 变得无法访问。在不是 UI 线程的线程上创建表单本身是可能的,但这意味着该表单只能由创建它的线程访问,因此这不太可能是您想要的。你得到了cross-thread exception因为你试图从另一个线程修改 UI 线程。

您可以尝试在后台线程上加载和处理所有数据,但将其加载到新的临时DataTable. 然后,在 UI 线程上使用DataSet.Merge(如果您使用的是 BackgroundWorker,则可能在RunWorkerCompleted事件中)并将临时 DataTable 与绑定到 DataGridView 的主 DataSet 合并。

That should mean all the processing and heavy work is done on a background thread, but the DataGridView control is updated on the UI thread, thus bypassing any invalid cross-threading. One side note is that you should test the performance of the DataSet.Merge.

于 2012-12-17T11:42:58.667 回答