マルチスレッドで複数のコレクション操作を排他制御して処理したかった

いろんなスレッドからObservableCollectionを操作する時コレクション操作するとDispatcher.Invokeとかで書かなきゃいけないので
http://okazuki.hatenablog.com/entry/20100112/1263267397
な感じでやったりしてました。

けど開発を進めていくと、一連の処理をロックした状態で行いたいケースが結構あるんですよね。
あとは重いコレクション操作処理をDispathcerスレッドで行いたくないときとか。
変更と削除と追加を一つの処理として行いたいとか。
lock(hogelock)
{
   // 変更処理
   // 削除処理
   // 追加処理
}
とか書けばよいんですけど、ロックオブジェクトの管理が・・・・

いろいろなスレッドからコレクション操作したい。
複数のコレクション操作にてデータの整合性を確保したい。
という要件を満たすための付け焼刃です。

```csharp

    public class TransactionDispatchObservableCollection<T> : ObservableCollection<T>
    {
        /// <summary>
        /// コレクションディスパッチャー
        /// </summary>
        public Dispatcher Dispatch { get; set; }

        public DispatcherPriority Priority { get; set; } = DispatcherPriority.Background;

        private object TransactLock = new object();

        #region コンストラクタ

        public TransactionDispatchObservableCollection(Dispatcher Dispatch)
        {
            this.Dispatch = Dispatch;
        }
        public TransactionDispatchObservableCollection(Dispatcher Dispatch, IEnumerable<T> collection) : base(collection)
        {
            this.Dispatch = Dispatch;
        }

        #endregion

        /// <summary>
        /// 関連処理を排他制御しながら実行します。
        /// </summary>
        /// <param name="action"></param>
        public void TransactExcution(Action action)
        {
            lock (TransactLock)
            {
                action();
            }
        }
        /// <summary>
        /// 関連処理を排他制御しながら実行します。(非同期)
        /// </summary>
        public async Task TransactExcutionAsync(Action action)
        {
            await Task.Run(() => {
                lock (TransactLock)
                {
                    action();
                }
            });
        }
        protected override void ClearItems()
        {
            TransactExcution(() => base.ClearItems());
        }
        protected override void InsertItem(int index, T item)
        {
            TransactExcution(() => base.InsertItem(index, item));
        }
        protected override void MoveItem(int oldIndex, int newIndex)
        {
            TransactExcution(() => base.MoveItem(oldIndex, newIndex));
        }
        protected override void SetItem(int index, T item)
        {
            TransactExcution(() => base.SetItem(index, item)); 
        }
        protected override void RemoveItem(int index)
        {
            TransactExcution(() => base.RemoveItem(index));
        }

        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            if (this.Dispatch.Thread == Thread.CurrentThread)
            {
                base.OnCollectionChanged(e);
            }
            else
            {
                Action<NotifyCollectionChangedEventArgs> changed = OnCollectionChanged;
                this.Dispatch.Invoke(changed, Priority, e);
            }
        }
    }
```

こんな感じで

```csharp

await list.TransactExcutionAsync(() =>
                {
                    if (!list.Any((x => x.Name == "Test")))
                    {
                        list.Add(model);
                    }
                });

```

色々ダメなんですが限定用とであれば使えるかなぁと。