Skip to content

Instantly share code, notes, and snippets.

@dealproc
Created November 24, 2014 19:25
Show Gist options
  • Save dealproc/e01e8aac2c2e447f651a to your computer and use it in GitHub Desktop.
Save dealproc/e01e8aac2c2e447f651a to your computer and use it in GitHub Desktop.
ThreadSafeObservableCollection.cs
using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows.Threading;
using Kiosk.Error;
using Kiosk.Globals;
namespace Kiosk.Gui.Types
{
[Serializable]
public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
[NonSerialized] private ReaderWriterLock _lock;
protected override void ClearItems()
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
if (null == _lock)
{
_lock = new ReaderWriterLock();
}
var c = _lock.UpgradeToWriterLock(-1);
base.ClearItems();
_lock.DowngradeFromWriterLock(ref c);
}
else
{
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { Clear(); });
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
protected override void InsertItem(int index, T item)
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
if (index > Count)
return;
if (null == _lock)
{
_lock = new ReaderWriterLock();
}
var c = _lock.UpgradeToWriterLock(-1);
base.InsertItem(index, item);
_lock.DowngradeFromWriterLock(ref c);
}
else
{
var e = new object[] {index, item};
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { InsertItemImpl(e); }, e);
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
private void InsertItemImpl(object[] e)
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
InsertItem((int) e[0], (T) e[1]);
}
else
{
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { InsertItemImpl(e); });
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
protected override void MoveItem(int oldIndex, int newIndex)
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
if (oldIndex >= Count | newIndex >= Count | oldIndex == newIndex)
return;
if (null == _lock)
{
_lock = new ReaderWriterLock();
}
var c = _lock.UpgradeToWriterLock(-1);
base.MoveItem(oldIndex, newIndex);
_lock.DowngradeFromWriterLock(ref c);
}
else
{
var e = new object[] {oldIndex, newIndex};
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { MoveItemImpl(e); }, e);
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
private void MoveItemImpl(object[] e)
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
MoveItem((int) e[0], (int) e[1]);
}
else
{
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { MoveItemImpl(e); });
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
protected override void RemoveItem(int index)
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
if (index >= Count)
return;
if (null == _lock)
{
_lock = new ReaderWriterLock();
}
var c = _lock.UpgradeToWriterLock(-1);
base.RemoveItem(index);
_lock.DowngradeFromWriterLock(ref c);
}
else
{
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { RemoveItem(index); }, index);
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
protected override void SetItem(int index, T item)
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
if (null == _lock)
{
_lock = new ReaderWriterLock();
}
var c = _lock.UpgradeToWriterLock(-1);
base.SetItem(index, item);
_lock.DowngradeFromWriterLock(ref c);
}
else
{
var e = new object[] {index, item};
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { SetItemImpl(e); }, e);
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
private void SetItemImpl(object[] e)
{
try
{
if (Constants.MainDispatcher.CheckAccess())
{
SetItem((int) e[0], (T) e[1]);
}
else
{
Constants.MainDispatcher.Invoke(DispatcherPriority.DataBind,
(SendOrPostCallback) delegate { SetItemImpl(e); });
}
}
catch (Exception ex)
{
Logging.LogException(ex);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment