虽然关于使用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;
}
}发布于 2014-06-09 19:06:01
没有InvalidOperationException,而不是证明了线程的安全性。Winforms只对非常特定的成员访问执行检查。它必须包含在底层操作系统调用中使用的句柄属性。这在您的代码中是不会发生的,DataGridView不会从Windows中获取其数据。
一个很明显的情况是它不会是线程安全的,就是允许用户继续编辑网格值。当然,您将得到一个与线程执行完全不同步的不可预测的值。您必须将DataGridView.ReadOnly属性设置为true,以防止这种情况发生。
那么,DataGridViewCell是如何获得其价值的,这非常重要。不明显的情况是它引发CellValueNeeded事件或网格被数据库化的情况。现在,这完全取决于代码是否是线程安全的。
发布于 2014-06-09 18:54:05
这不安全。
控件,特别是dataGrid,将使用幕后的Collection类。当其他线程可能编辑时,读取它们是不安全的。
读取某些属性(即SelecteItem)将需要句柄并触发跨线程警告异常。
https://stackoverflow.com/questions/24126814
复制相似问题