Межпоточная безопасность GUI в .NET при чтении, но НЕ при обновлении элемента управления DataGridView

Хотя на SO есть масса вопросов/ответов относительно обновления элемента управления GUI из рабочего потока с использованием 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;
        }
    }

person dizzy.stackoverflow    schedule 09.06.2014    source источник
comment
В общем, когда вашему фоновому рабочему процессу требуется информация из пользовательского интерфейса для выполнения своей работы, вы должны получить информацию из пользовательского интерфейса до запуска рабочего процесса, а затем передать копию информации рабочему процессу. Вы должны извлекать из пользовательского интерфейса внутри работника только в том случае, если действительно необходимо изменить информацию после запуска работника.   -  person Servy    schedule 09.06.2014
comment
Спасибо. Понимая, что это не обязательно хорошая практика кодирования, вопрос направлен на развитие более глубокого уровня понимания того, что безопасно и что небезопасно, в отличие от того, что является разумной или неразумной практикой кодирования. :)   -  person dizzy.stackoverflow    schedule 09.06.2014


Ответы (2)


Отсутствие InvalidOperationException не доказывает потокобезопасность. Winforms выполняет проверку только для доступа к очень конкретным членам. Он должен включать свойство Handle, используемое в базовом вызове операционной системы. Это никогда не произойдет в вашем коде, DataGridView не получает данные из вызовов Windows.

Очевидный случай, когда он не будет потокобезопасным, — это когда вы разрешаете пользователю продолжать редактировать значения сетки. Вы, конечно, получите непредсказуемое значение, которое полностью не синхронизировано с выполнением потока. Вам нужно будет установить для свойства DataGridView.ReadOnly значение true, чтобы этого не произошло.

Тогда очень важно, как DataGridViewCell получает свое значение. Неочевидные случаи — это случаи, когда вызывается событие CellValueNeeded или когда сетка привязана к данным. Теперь это полностью зависит от того, является ли этот код потокобезопасным.

person Hans Passant    schedule 09.06.2014
comment
Чтобы было ясно, давайте предположим, что нас не волнует, является ли читаемое нами значение синхронизированным/точным. На самом деле вопрос заключается в том, можем ли мы безопасно прочитать значение, ничего не нарушая и не получая исключения во время выполнения. Может случиться так, что мы читаем значение, которое является неточным из-за отсутствия синхронизации, но вызовет ли это когда-либо исключение во время выполнения из-за небезопасности? - person dizzy.stackoverflow; 09.06.2014
comment
У вас это ужасно задом наперёд. Исключения — это хорошо, они сообщают вам, что что-то пошло не так. Чего вам следует опасаться, так это несинхронизированных обращений, которые не генерируют исключение. Но просто плохие данные и нет возможности узнать, что вы производите ненужный результат. Повторюсь: Деда Мороза здесь нет, исключения не будет. - person Hans Passant; 09.06.2014

Это небезопасно.

Элементы управления, особенно dataGrid, будут использовать классы Collection под капотом. Их небезопасно читать, когда другие темы могут редактировать.

Чтение некоторых свойств (например, SelecteItem) потребует дескриптора и вызовет исключение с предупреждением о перекрестном потоке.

person Henk Holterman    schedule 09.06.2014