У меня есть приложение Windows Forms, которое отображает форму с DataGridView, привязанной к пользовательской коллекции, которая наследует BindingList. Я использую механизм BindingSource / DataSource для привязки данных. Форма представляет собой монитор, который отображает информацию о состоянии, содержащуюся в коллекции. Каждый элемент коллекции представляет информацию о состоянии одного из множества дочерних потоков.
Я использую подход SynchronizationContext, чтобы удостовериться, что событие ListChanged из моей коллекции синхронизировано с потоком пользовательского интерфейса и не возникает проблем с многопоточностью. Тем не менее, кажется, что несколько потоков могут работать с коллекцией одновременно. Это вызывает проблемы с привязкой данных. Ниже приведен пример произошедшего исключения:
System.ArgumentOutOfRangeException:
Указанный аргумент был вне
диапазон допустимых значений. Имя параметра:
rowIndex в
System.Windows.Forms.DataGridView.GetCellDisplayRectangle (Int32
columnIndex, Int32 rowIndex, Boolean
cutOverflow) в
System.Windows.Forms.DataGridView.GetCellAdjustedDisplayRectangle (Int32
columnIndex, Int32 rowIndex, Boolean
cutOverflow) в
System.Windows.Forms.DataGridView.InvalidateCellPrivate (Int32
columnIndex, Int32 rowIndex) в
System.Windows.Forms.DataGridView.OnCellCommonChange (Int32
columnIndex, Int32 rowIndex) в
System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged (ListChangedEventArgs
есть
System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged (Объект
отправитель, ListChangedEventArgs e) в
System.Windows.Forms.CurrencyManager.OnListChanged (ListChangedEventArgs
есть
System.Windows.Forms.CurrencyManager.List_ListChanged (Объект
отправитель, ListChangedEventArgs e) в
System.Windows.Forms.BindingSource.OnListChanged (ListChangedEventArgs
есть
System.Windows.Forms.BindingSource.InnerList_ListChanged (Объект
отправитель, ListChangedEventArgs e)
Это заставляет меня поверить, что коллекция была снова изменена после того, как начальное событие ListChanged было инициировано и обработано потоком пользовательского интерфейса.
Итак, мой вопрос заключается в том, как сделать мою коллекцию не только поточно-ориентированной, но и блокирующей, чтобы пользовательский интерфейс мог обновляться после события ListChanged, прежде чем разрешено другое изменение? Недостаточно ставить в очередь события ListChanged, мне нужно заблокировать операцию, которая привела к запуску события ListChanged. Например, если я изменил свойство элемента, а затем вызвал событие ListChanged (ListChangedType = ItemChanged), другой поток, который пытается добавить элемент в коллекцию, блокируется до тех пор, пока не вернутся обработчики событий ListChanged.
Есть идеи?