Межпотоковая безопасность графического интерфейса в.NET при чтении, но НЕ при обновлении элемента управления DataGridView
Несмотря на массу вопросов / ответов по SO, касающихся обновления элемента управления с графическим интерфейсом из рабочего потока с помощью Control.Invoke, я не смог получить ясность по теме чтения данных из элемента управления без его обновления.
Пример: у меня есть DataGridView в форме Windows. Из рабочего потока я хочу проверить значение определенной ячейки в 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;
}
}
2 ответа
Отсутствие InvalidOperationException не доказывает безопасность потоков. Winforms выполняет проверку только для очень определенных членов доступа. Он должен включать свойство Handle, используемое в базовом вызове операционной системы. Это никогда не произойдет в вашем коде, DataGridView не получает свои данные из вызовов Windows.
Очевидный случай, когда он не будет потокобезопасным, - это когда вы позволяете пользователю продолжить редактирование значений сетки. Вы, конечно, получите непредсказуемое значение, которое полностью не синхронизировано с выполнением потока. Вам нужно будет установить для свойства DataGridView.ReadOnly значение true, чтобы этого не происходило.
Тогда очень важно, как DataGridViewCell получает свое значение. Неочевидные случаи - это случаи, когда оно вызывает событие CellValueNeeded или когда сетка привязана к базе данных. Теперь все зависит от того , является ли этот код потокобезопасным.
Это не безопасно.
Элементы управления, особенно dataGrid, будут использовать классы Collection под капотом. Их небезопасно читать, когда другие темы могут редактировать.
Чтение некоторых свойств (например, SelecteItem) потребует дескриптора и запускает исключение предупреждения о перекрестном потоке