Реализуйте потокобезопасный сбор для привязки данных в .NET - PullRequest
0 голосов
/ 27 мая 2009

У меня есть приложение Windows Forms, которое отображает форму с DataGridView, привязанной к пользовательской коллекции, которая наследует BindingList. Я использую механизм BindingSource / DataSource для привязки данных. Форма представляет собой монитор, который отображает информацию о состоянии, содержащуюся в коллекции. Каждый элемент коллекции представляет информацию о состоянии одного из множества дочерних потоков.

Я использую подход SynchronizationContext, чтобы удостовериться, что событие ListChanged из моей коллекции синхронизировано с потоком пользовательского интерфейса и не возникает проблем с многопоточностью. Тем не менее, кажется, что несколько потоков могут работать с коллекцией одновременно. Это вызывает проблемы с привязкой данных. Ниже приведен пример произошедшего исключения:

> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: rowIndex
>    at System.Windows.Forms.DataGridView.GetCellDisplayRectangle(Int32 columnIndex, Int32 rowIndex, Boolean cutOverflow)
>    at System.Windows.Forms.DataGridView.GetCellAdjustedDisplayRectangle(Int32 columnIndex, Int32 rowIndex, Boolean cutOverflow)
>    at System.Windows.Forms.DataGridView.InvalidateCellPrivate(Int32 columnIndex, Int32 rowIndex)
>    at System.Windows.Forms.DataGridView.OnCellCommonChange(Int32 columnIndex, Int32 rowIndex)
>    at System.Windows.Forms.DataGridView.DataGridViewDataConnection.ProcessListChanged(ListChangedEventArgs e)
>    at System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(Object sender, ListChangedEventArgs e)
>    at System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs e)
>    at System.Windows.Forms.CurrencyManager.List_ListChanged(Object sender, ListChangedEventArgs e)
>    at System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs e)
>    at System.Windows.Forms.BindingSource.InnerList_ListChanged(Object sender, ListChangedEventArgs e)

Это заставляет меня поверить, что коллекция была снова изменена после того, как начальное событие ListChanged было инициировано и обработано потоком пользовательского интерфейса.

Итак, мой вопрос состоит в том, как сделать мою коллекцию не только поточно-ориентированной, но и блокирующей, чтобы пользовательский интерфейс мог обновляться после события ListChanged, прежде чем разрешено другое изменение? Недостаточно ставить в очередь события ListChanged, мне нужно заблокировать операцию, которая привела к запуску события ListChanged. Например, если я изменил свойство элемента, а затем вызвал событие ListChanged (ListChangedType = ItemChanged), другой поток, который пытается добавить элемент в коллекцию, блокируется до тех пор, пока не вернутся обработчики событий ListChanged.

Есть идеи?

1 Ответ

0 голосов
/ 28 мая 2009

Вы можете просто обернуть это с вашей собственной реализацией любого интерфейса, который вы хотите. Взгляните на этот ответ на тот же вопрос ...

...