虽然关于使用Control.Invoke从工作线程更新GUI控件有很多关于SO的问题/答案,但是我无法清楚地了解从控件读取数据而不更新它的主题。
示例:我在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;
}
}
答案 0 :(得分:5)
缺少InvalidOperationException 不证明线程安全。 Winforms仅对非常特定的成员访问执行检查。它必须涉及Handle属性,用于底层操作系统调用。这将在您的代码中永远发生,DataGridView不会从Windows调用中获取其数据。
一个明显的情况是它不是线程安全的,你允许用户继续编辑网格值。您当然会得到一个与线程执行完全不同步的不可预测的值。您必须将DataGridView.ReadOnly属性设置为 true 以防止这种情况发生。
然后,DataGridViewCell如何获取其值非常重要。非显而易见的情况是它引发CellValueNeeded事件或网格是数据绑定的情况。现在它完全取决于 代码是否是线程安全的。
答案 1 :(得分:2)
这不安全。
控件,尤其是dataGrid,将使用引擎盖下的Collection类。当其他线程可能编辑时,它们不安全。
读取一些属性(即SelecteItem)将需要一个Handle并触发跨线程警告异常。