我有一个Windows窗体应用程序,它显示一个表单,其中DataGridView绑定到继承BindingList的自定义集合。我正在使用BindingSource / DataSource机制进行数据绑定。表单是一个监视器,显示集合中包含的状态信息。集合中的每个元素表示许多子线程之一的状态信息。
我正在使用SynchronizationContext方法来确保我的集合中的ListChanged事件与UI线程同步,并且不会发生跨线程问题。但是,似乎多个线程仍然可以同时使用该集合。这会导致数据绑定问题。以下是已发生的异常的示例:
System.ArgumentOutOfRangeException: 指定的论点不合时宜 有效值范围。参数名称: 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 吃 System.Windows.Forms.DataGridView.DataGridViewDataConnection.currencyManager_ListChanged(对象 sender,ListChangedEventArgs e)at System.Windows.Forms.CurrencyManager.OnListChanged(ListChangedEventArgs 吃 System.Windows.Forms.CurrencyManager.List_ListChanged(对象 sender,ListChangedEventArgs e)at System.Windows.Forms.BindingSource.OnListChanged(ListChangedEventArgs 吃 System.Windows.Forms.BindingSource.InnerList_ListChanged(对象 sender,ListChangedEventArgs e)
这让我相信在最初的ListChanged事件被引发并由UI线程处理后,该集合再次被更改。
所以,我的问题是如何使我的集合不仅是线程安全的而且是阻塞的,以便在允许另一个更改之前,在ListChanged事件之后UI可以刷新?排队ListChanged事件是不够的,我需要阻止导致ListChanged事件被触发的操作。例如,如果我更改了元素的属性然后引发了ListChanged事件(ListChangedType = ItemChanged),则阻止尝试将项添加到集合的另一个线程,直到ListChanged事件处理程序返回。
有什么想法吗?
答案 0 :(得分:0)
将视图绑定到集合的副本,然后适当地控制对集合的访问:确保线程在lock()部分中进行更新,并确保使用同一对象上的lock()完成复制。
这也可以让你对写入请求进行排队,这样编写器就不会阻塞,只是发送带有更新的消息,这可能有助于提高性能。
只是一个想法。
答案 1 :(得分:0)
尝试ConcurrentBag<T>