在.NET中实现数据绑定的线程安全集合

时间:2009-05-27 18:29:57

标签: .net multithreading collections data-binding

我有一个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事件处理程序返回。

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

将视图绑定到集合的副本,然后适当地控制对集合的访问:确保线程在lock()部分中进行更新,并确保使用同一对象上的lock()完成复制。

这也可以让你对写入请求进行排队,这样编写器就不会阻塞,只是发送带有更新的消息,这可能有助于提高性能。

只是一个想法。

答案 1 :(得分:0)

尝试ConcurrentBag<T>