andrew4582

ThreadSafeObservableCollection

Aug 18th, 2012
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.40 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections.ObjectModel;
  6. using System.Windows.Threading;
  7. using System.Threading;
  8. using System.Collections.Specialized;
  9. using System.ComponentModel;
  10. using System.Windows;
  11.  
  12. namespace System.Windows.Threading
  13. {
  14.     public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
  15.     {
  16.  
  17.         Dispatcher _dispatcher;
  18.         ReaderWriterLock _lock;
  19.  
  20.         public ThreadSafeObservableCollection()
  21.         {
  22.             _dispatcher = Dispatcher.CurrentDispatcher;
  23.             if (_dispatcher != Application.Current.Dispatcher)
  24.                 _dispatcher = Application.Current.Dispatcher;
  25.             _lock = new ReaderWriterLock();
  26.         }
  27.  
  28.         protected override void ClearItems()
  29.         {
  30.             if (_dispatcher.CheckAccess())
  31.             {
  32.                 LockCookie c = _lock.UpgradeToWriterLock(-1);
  33.                 base.ClearItems();
  34.                 _lock.DowngradeFromWriterLock(ref c);
  35.             }
  36.             else
  37.             {
  38.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { Clear(); },null);
  39.             }
  40.         }
  41.         protected override void InsertItem(int index, T item)
  42.         {
  43.             if (_dispatcher.CheckAccess())
  44.             {
  45.                 if (index > this.Count)
  46.                     return;
  47.                 LockCookie c = _lock.UpgradeToWriterLock(-1);
  48.                 base.InsertItem(index, item);
  49.                 _lock.DowngradeFromWriterLock(ref c);
  50.             }
  51.             else
  52.             {
  53.                 object[] e = new object[] { index, item };
  54.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { InsertItemImpl(e); }, e);
  55.             }
  56.  
  57.         }
  58.         void InsertItemImpl(object[] e)
  59.         {
  60.             if (_dispatcher.CheckAccess())
  61.             {
  62.                 InsertItem((int)e[0], (T)e[1]);
  63.             }
  64.             else
  65.             {
  66.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { InsertItemImpl(e); });
  67.             }
  68.         }
  69.         protected override void MoveItem(int oldIndex, int newIndex)
  70.         {
  71.             if (_dispatcher.CheckAccess())
  72.             {
  73.                 if (oldIndex >= this.Count | newIndex >= this.Count | oldIndex == newIndex)
  74.                     return;
  75.                 LockCookie c = _lock.UpgradeToWriterLock(-1);
  76.                 base.MoveItem(oldIndex, newIndex);
  77.                 _lock.DowngradeFromWriterLock(ref c);
  78.             }
  79.             else
  80.             {
  81.                 object[] e = new object[] { oldIndex, newIndex };
  82.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { MoveItemImpl(e); }, e);
  83.             }
  84.         }
  85.         void MoveItemImpl(object[] e)
  86.         {
  87.             if (_dispatcher.CheckAccess())
  88.             {
  89.                 MoveItem((int)e[0], (int)e[1]);
  90.             }
  91.             else
  92.             {
  93.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { MoveItemImpl(e); });
  94.             }
  95.         }
  96.         protected override void RemoveItem(int index)
  97.         {
  98.  
  99.             if (_dispatcher.CheckAccess())
  100.             {
  101.                 if (index >= this.Count)
  102.                     return;
  103.                 LockCookie c = _lock.UpgradeToWriterLock(-1);
  104.                 base.RemoveItem(index);
  105.                 _lock.DowngradeFromWriterLock(ref c);
  106.             }
  107.             else
  108.             {
  109.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { RemoveItem(index); }, index);
  110.             }
  111.         }
  112.         protected override void SetItem(int index, T item)
  113.         {
  114.             if (_dispatcher.CheckAccess())
  115.             {
  116.                 LockCookie c = _lock.UpgradeToWriterLock(-1);
  117.                 base.SetItem(index, item);
  118.                 _lock.DowngradeFromWriterLock(ref c);
  119.             }
  120.             else
  121.             {
  122.                 object[] e = new object[] { index, item };
  123.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { SetItemImpl(e); }, e);
  124.             }
  125.         }
  126.         void SetItemImpl(object[] e)
  127.         {
  128.             if (_dispatcher.CheckAccess())
  129.             {
  130.                 SetItem((int)e[0], (T)e[1]);
  131.             }
  132.             else
  133.             {
  134.                 _dispatcher.Invoke(DispatcherPriority.Input, (SendOrPostCallback)delegate { SetItemImpl(e); });
  135.             }
  136.         }
  137.  
  138.         public override event NotifyCollectionChangedEventHandler CollectionChanged;
  139.  
  140.         protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  141.         {
  142.             if (this.CollectionChanged != null)
  143.             {
  144.                 using (IDisposable locker = BlockReentrancy())
  145.                 {
  146.                     foreach (Delegate invoker in CollectionChanged.GetInvocationList())
  147.                     {
  148.                         NotifyCollectionChangedEventHandler handler = (NotifyCollectionChangedEventHandler)invoker;
  149.                         DispatcherObject dispatcherInvoker = invoker.Target as DispatcherObject;
  150.                         ISynchronizeInvoke syncInvoker = invoker.Target as ISynchronizeInvoke;
  151.                         if (dispatcherInvoker != null)
  152.                         {
  153.                             dispatcherInvoker.Dispatcher.Invoke(DispatcherPriority.DataBind,
  154.                                 (NotifyCollectionChangedEventHandler)delegate(object s, NotifyCollectionChangedEventArgs ex)
  155.                                 {
  156.                                     handler(s, ex);
  157.                                 }, this, e);
  158.                         }
  159.                         else if (syncInvoker != null)
  160.                         {
  161.                             syncInvoker.Invoke(invoker, new object[] { this, e });
  162.                         }
  163.                         else
  164.                         {
  165.                             handler(this, e);
  166.                         }
  167.                     }
  168.                 }
  169.             }
  170.         }
  171.  
  172.  
  173.         public T[] ToSyncArray()
  174.         {
  175.             _lock.AcquireReaderLock(-1);
  176.             T[] _sync = new T[this.Count];
  177.             this.CopyTo(_sync, 0);
  178.             _lock.ReleaseReaderLock();
  179.             return _sync;
  180.         }
  181.     }
  182. }
Advertisement
Add Comment
Please, Sign In to add comment