調査してたらこんな問題が…
前、StatefulModel を魔改造して使っているといってましたが、ロック回数とか減らすために AddRange とかの複数オブジェクトを一度に追加するバージョンのメソッドを追加しているんです (ろくにテストはしてないんですけどね)
今までだとこう実装してたわけですよ。
public void AddRange(IEnumerable<T> items)
{
if (items == null) throw new ArgumentNullException(nameof(items));
if (items.Count() == 0) throw new ArgumentException(nameof(items));
ReadAndWriteWithLockAction(
() =>
{
foreach (var item in items)
{
this._list.Add(item);
}
},
() =>
{
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items.ToArray(), this._list.Count - itemsList.Length));
});
}
でまあ IE<T> の忘れがちな落とし穴で遅延実行なわけじゃないですか。でまあ、foreach と ToArray() で二回動くんで、別々のオブジェクトができるんですよね。正しくは以下のように実装しました。
public void AddRange(IEnumerable<T> items)
{
if (items == null) throw new ArgumentNullException(nameof(items));
var count = items.Count();
if (count == 0) throw new ArgumentException(nameof(items));
// 予め配列にでも書きだしておく
var ary = new T[count];
var idx = 0;
foreach (var item in items) ary[idx++] = item;
ReadAndWriteWithLockAction(
() =>
{
foreach (var item in ary)
{
this._list.Add(item);
}
},
() =>
{
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, ary.ToArray(), this._list.Count - itemsList.Length));
});
}
やらかしてしまった事象ですね。いかんです。