我有一个Windows窗体应用程序,它显示一个表单,其中DataGridView绑定到继承BindingList的自定义集合。我正在使用BindingSource / DataSource机制进行数据绑定。表单是一个监视器,显示集合中包含的状态信息。集合中的每个元素表示许多子线程之一的状态信息。
我正在使用SynchronizationContext方法来确保我的集合中的ListChanged事件与UI线程同步,并且不会发生跨线程问题。但是,似乎多个线程仍然可以同时使用该集合。这会导致数据绑定问题。以下是已发生的异常的示例:
> 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事件被引发并由UI线程处理后,该集合再次被更改。
所以,我的问题是如何使我的集合不仅是线程安全的而且是阻塞的,以便在允许另一个更改之前,在ListChanged事件之后UI可以刷新?排队ListChanged事件是不够的,我需要阻止导致ListChanged事件被触发的操作。例如,如果我更改了元素的属性然后引发了ListChanged事件(ListChangedType = ItemChanged),则阻止尝试将项添加到集合的另一个线程,直到ListChanged事件处理程序返回。
有什么想法吗?