【问题标题】:GUI cross-thread safety in .NET when reading but NOT updating DataGridView Control读取但不更新 DataGridView 控件时 .NET 中的 GUI 跨线程安全
【发布时间】:2014-07-30 09:05:59
【问题描述】:

虽然有大量关于使用 Control.Invoke 从工作线程更新 GUI 控件的问题/答案,但我无法弄清楚从控件读取数据而不更新它的主题。

示例:我在 Windows 窗体上有一个 DataGridView。从工作线程中,我想检查 DGV 上特定单元格的值,但我不需要/不想更新该值。从工作线程中,我调用一个方法,该方法将 DataGridView 对象作为其唯一参数,然后该方法检查 DataGridView 中的特定单元格但不修改它,在这种情况下我需要使用 .Invoke 吗?

现在代码似乎运行良好,没有使用 .Invoke 的明显警告。但是,我不清楚这是否安全,因为它不会更新 DGV,而是只查看 DGV 的单元而不修改任何单元。

有人可以解释一下吗?如果这是一个重复的问题,我很抱歉,但我找不到任何其他问题,这些问题专注于在多线程情况下仅读取控件而不更新/修改它。

谢谢。

从工作线程调用的示例方法:

    private DataGridViewRow getRowObject(DataGridView dgv)
    {
        foreach (DataGridViewRow row in dgv.Rows)
        {
                if ((int)dgv[specialColumn, row.Index].Value == 100)                    
                return row;
        }
    }

【问题讨论】:

  • 一般来说,当您的后台工作人员需要来自 UI 的信息来完成其工作时,您应该在启动工作人员之前从 UI 获取信息,然后传递一份给工人的信息。只有在工作人员启动后确实需要更改信息时,您才应该从工作人员内的 UI 中提取。
  • 谢谢。了解这不一定是好的编码实践,这个问题旨在更深入地了解什么是安全的,什么是不安全的,而不是什么是聪明的或不聪明的编码实践。 :)

标签: c# multithreading winforms datagridview invokerequired


【解决方案1】:

这不安全。

控件,尤其是他的 dataGrid,将在后台使用 Collection 类。当其他线程可能编辑时,它们不安全阅读。

读取一些属性(即SelecteItem)将需要一个Handle并触发Cross-thread warning Exception。

【讨论】:

    【解决方案2】:

    没有 InvalidOperationException 并证明线程安全。 Winforms 只检查非常具体的成员访问。它必须涉及在底层操作系统调用中使用的 Handle 属性。这永远不会在您的代码中发生,DataGridView 不会从 Windows 调用中获取其数据。

    它不是线程安全的一个明显情况是您允许用户继续编辑网格值。您当然会得到一个与线程执行完全不同步的不可预测的值。您必须将 DataGridView.ReadOnly 属性设置为 true 以防止这种情况发生。

    那么 DataGridViewCell 如何获得它的值就很重要了。不明显的情况是它引发 CellValueNeeded 事件或网格是数据绑定的情况。现在这完全取决于那个代码是否是线程安全的。

    【讨论】:

    • 为了清楚起见,假设我们不关心我们读取的值是否同步/准确。问题实际上是关于我们是否可以在不“破坏”任何东西或获得运行时异常的情况下安全地读取该值。我们可能会因为没有同步而读取一个不准确的值,但这是否会因为“不安全”而产生运行时异常?
    • 你有这个可怕的倒退。例外是好的,它们告诉你出了问题。您必须害怕的是不会生成异常的非同步访问。但只是糟糕的数据,没有办法发现你正在产生垃圾结果。重申:这里没有圣诞老人,你不会得到例外。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    相关资源
    最近更新 更多