ObservableCollection中的BlockReentrancy <T>

Max*_*ich 24 .net c# collections events observablecollection

请有人能够向我解释一下该BlockReentrancy方法的目的是ObservableCollection<T>什么?

MSDN以下面的示例显示:

//The typical usage is to wrap an OnCollectionChanged call within a using scope, as in the following example:

using (BlockReentrancy())
{
    // OnCollectionChanged call
}
Run Code Online (Sandbox Code Playgroud)

但这似乎并没有为我澄清目的是什么.有人在乎解释吗?

Ric*_*key 27

一个ObservableCollection工具INotifyCollectionChanged,所以它有一个CollectionChanged事件.如果此事件有订阅者,则他们可以在收集已经处于通知过程中时进一步修改收集.由于CollectionChanged事件跟踪确切地改变了什么,这种交互可能变得非常混乱.

因此ObservableCollection,作为一种特殊情况,允许CollectionChanged事件的单个订阅者从其处理程序修改集合.但是,如果事件有两个或更多订阅者,则不允许CollectionChanged处理程序修改集合.CollectionChanged

在对方法BlockReentrancyCheckReentancy用于实现此逻辑.它BlockReentrancyOnCollectionChanged方法的开头使用,并CheckReentancy用于修改集合的所有方法.


Ale*_*Aza 12

这是实施 BlockReentrancy()

protected IDisposable BlockReentrancy()
{
   this._monitor.Enter();
   return this._monitor;
}
Run Code Online (Sandbox Code Playgroud)

还有另一种方法 CheckReentrancy()

protected void CheckReentrancy()
{
    if ((this._monitor.Busy && (this.CollectionChanged != null)) && (this.CollectionChanged.GetInvocationList().Length > 1))
    {
        throw new InvalidOperationException(SR.GetString("ObservableCollectionReentrancyNotAllowed"));
    }
}
Run Code Online (Sandbox Code Playgroud)

这样的方法为ClearItems,InsertItem,MoveItem,RemoveItem,SetItem检查CheckReentrancy()修改集合之前.

因此,下面的代码保证不会在内部更改集合using,但仅限于有多个处理程序订阅CollectionChanged事件.

using BlockReentrancy())
{
    CollectionChanged(this, e);
}
Run Code Online (Sandbox Code Playgroud)

这个例子展示了效果 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)
{
}
Run Code Online (Sandbox Code Playgroud)