title: Implement thread-safe collection for data-binding in .NET
body: <p>I have a Windows Forms application that displays a form with a DataGridView bound to a custom collection that inherits BindingList.  I'm using the BindingSource / DataSource mechanism for data-binding.  The form is a monitor that displays status information contained in the collection.  Each element of the collection represents status information for one of many child threads.</p>
  
  <p>I am using the SynchronizationContext approach to make sure that the ListChanged event from my collection is synchronized with the UI thread and no cross-threading issues occur.  However, it appears that it is still possible for multiple threads to work with the collection at the same time.  This causes problems with data-binding.  Below is an example of an exception that has occurred:</p>
  
  <blockquote>
    <p>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)</p>
  </blockquote>
  
  <p>This makes me believe that the collection was changed again after the initial ListChanged event was raised and being handled by the UI thread.</p>
  
  <p>So, my question is how to make my collection not only thread-safe but blocking so that the UI can refresh after a ListChanged event before another change is allowed?  It's not enough to queue the ListChanged events, I need to block the operation that led to the ListChanged event being fired.  For example, if I change the property of an element then raised the ListChanged event (ListChangedType = ItemChanged), another thread that is trying to add an item to the collection is blocked until the ListChanged event handler(s) return.</p>
  
  <p>Any ideas?</p>