Could someone please be kind enough to explain to me what the purpose of the BlockReentrancy
Method is in the ObservableCollection<T>
?
MSDN shows the following as an example:
//The typical usage is to wrap an OnCollectionChanged call within a using scope, as in the following example:
using (BlockReentrancy())
{
// OnCollectionChanged call
}
But this doesn't seem to clarify for me what the purpose is. Anyone care to explain?
An ObservableCollection
implements INotifyCollectionChanged
and so it has a CollectionChanged
event. If there is a subscriber to this event, they could further modify the collection while the collection is already in the process of notification. Since the CollectionChanged
event keeps track of exactly what changed, this interaction can get very messy.
As a result, the ObservableCollection
allows, as a special case, a single subscriber of the CollectionChanged
event to modify the collection from its handler. But it disallows modifying the collection from the CollectionChanged
handler if there are two or more subscribers to the CollectionChanged
event.
The pair of methods BlockReentrancy
and CheckReentancy
are used to implement this logic. The BlockReentrancy
is used at the start of the OnCollectionChanged
method and CheckReentancy
is used in all methods that modify the collection.
This is implementation of BlockReentrancy()
protected IDisposable BlockReentrancy()
{
this._monitor.Enter();
return this._monitor;
}
There is another method CheckReentrancy()
protected void CheckReentrancy()
{
if ((this._monitor.Busy && (this.CollectionChanged != null)) && (this.CollectionChanged.GetInvocationList().Length > 1))
{
throw new InvalidOperationException(SR.GetString("ObservableCollectionReentrancyNotAllowed"));
}
}
Such methods as ClearItems
, InsertItem
, MoveItem
, RemoveItem
, SetItem
check CheckReentrancy()
before modifying collection.
So the code below guarantees that collection will not be changed inside of using
, but only if there is more than one handler subscribed to CollectionChanged
event.
using BlockReentrancy())
{
CollectionChanged(this, e);
}
This example demonstrates effect of BlockReentrancy()
private static void Main()
{
collection.CollectionChanged += CollectionCollectionChanged1;
collection.CollectionChanged += CollectionCollectionChanged2;
collection.Add(1);
}
private static void CollectionCollectionChanged1(object sender, NotifyCollectionChangedEventArgs e)
{
collection.Add(2); // this line will throw exception
}
private static void CollectionCollectionChanged2(object sender, NotifyCollectionChangedEventArgs e)
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With