DataGridView 可编辑时 DataGridView / 数据集的线程安全更新

Posted

技术标签:

【中文标题】DataGridView 可编辑时 DataGridView / 数据集的线程安全更新【英文标题】:Threadsafe Updating of DataGridView / Dataset When DataGridView is Editable 【发布时间】:2011-03-14 16:53:00 【问题描述】:

我有一个包含 Dataset ds 和 DataGridView dgv 的 WinForms 应用程序。 dgv 绑定到 ds。

ds 通过 Task() 更新,该 Task() 使用 TableAdapter.Fill() 方法定期查询数据库。我在这里遇到了两个问题。

    当 ds 更新时,dgv 不会刷新,除非调整窗口大小或其他事件导致表单重绘。

    当用户开始编辑 dgv 中的单元格时,ds 会更新并由于多个线程访问同一 GUI 控件而导致 UI 崩溃。我尝试使用由 DataGridView dgv 中的某些事件设置的标志 EditModeOn,但这无助于防止线程错误。

拥有可由用户编辑并通过更改绑定数据集(在另一个线程中更新)来更新 DataGridView 的最佳方式是什么?

【问题讨论】:

【参考方案1】:

对于您的第 2 点,您可以使用 Control 类中的函数 Invoke。该函数将在 UI 线程中执行该函数。

http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

例如。 :

// Invoke an anonymous method on the thread of the form.
this.Invoke((MethodInvoker) delegate

    //Call your function to update your datagridview with the dataset in parameters
    ...
);

【讨论】:

【参考方案2】:

在第 1 点上,您可以通过调用 Form.Invalidate() 轻松解决此问题。这将导致您的表单重新绘制自己;这有点脏,但应该可以解决问题。

关于第 2 点,如果您有一个任务正在从另一个线程更新控件的内容,那么您应该总是得到一个异常,因为从任何线程访问控件都是非法的除了 UI 线程(创建 UI 的线程)。所以我不太清楚你是怎么做到的。

但是,我要做的是使用线程来检索结果,然后将这些结果存储在成员变量(字段)中。然后定期检查该字段以查看数据是否需要刷新,是否从该字段中获取数据并将其放入您的网格中,然后将该字段清空。您可以使用System.Windows.Forms.Timer 类的Tick 事件来实现此定期检查。

在您的更新例程中,您可以检查您的标志以查看网格是否正在被编辑,并在以后忽略更新。

【讨论】:

DataGridView 类的正确标志或成员变量是什么来检查网格是否正在被编辑? 抱歉,按 Enter 有点太快了 - 我的其他评论是关于我如何更新 DataGridView。我的线程只是更新了绑定到DataGridView的DataSet(不是直接调用refresh或者repaint方法,只是修改了底层数据集)。 该标志有点无关紧要,只需将布尔字段设置为 true 就足够了。如果数据网格绑定到该数据集,并且您在不同的线程上更新数据集,并且该更新会触发需要更新的网格通知;所有这些都发生在导致跨线程异常的“后台线程”的上下文中。人们有时很难理解。

以上是关于DataGridView 可编辑时 DataGridView / 数据集的线程安全更新的主要内容,如果未能解决你的问题,请参考以下文章

C# 如何使datagridview中的单元格处于可编辑

datagridview内容设置不可编辑

datagridview内容设置不可编辑

编辑绑定的 DataGridView 后防止列自动排序

怎么让datagridview不自动修改绑定的datatable

将 DataTable 绑定到已定义列的 Datagridview