Created
May 17, 2011 18:18
-
-
Save danielmarbach/977029 to your computer and use it in GitHub Desktop.
Thread safe observable collection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[DebuggerDisplay("Count = {Count}")] | |
[ComVisible(false)] | |
public class SafeObservableCollection<T> : ObservableCollection<T> | |
{ | |
private readonly Dispatcher dispatcher; | |
public SafeObservableCollection() | |
: this(Enumerable.Empty<T>()) | |
{ | |
} | |
public SafeObservableCollection(Dispatcher dispatcher) | |
: this(Enumerable.Empty<T>(), dispatcher) | |
{ | |
} | |
public SafeObservableCollection(IEnumerable<T> collection) | |
: this(collection, Dispatcher.CurrentDispatcher) | |
{ | |
} | |
public SafeObservableCollection(IEnumerable<T> collection, Dispatcher dispatcher) | |
{ | |
this.dispatcher = dispatcher; | |
foreach (T item in collection) | |
{ | |
this.Add(item); | |
} | |
} | |
protected override void SetItem(int index, T item) | |
{ | |
this.ExecuteOrInvoke(() => this.SetItemBase(index, item)); | |
} | |
protected override void MoveItem(int oldIndex, int newIndex) | |
{ | |
this.ExecuteOrInvoke(() => this.MoveItemBase(oldIndex, newIndex)); | |
} | |
protected override void ClearItems() | |
{ | |
this.ExecuteOrInvoke(this.ClearItemsBase); | |
} | |
protected override void InsertItem(int index, T item) | |
{ | |
this.ExecuteOrInvoke(() => this.InsertItemBase(index, item)); | |
} | |
protected override void RemoveItem(int index) | |
{ | |
this.ExecuteOrInvoke(() => this.RemoveItemBase(index)); | |
} | |
private void RemoveItemBase(int index) | |
{ | |
base.RemoveItem(index); | |
} | |
private void InsertItemBase(int index, T item) | |
{ | |
base.InsertItem(index, item); | |
} | |
private void ClearItemsBase() | |
{ | |
base.ClearItems(); | |
} | |
private void MoveItemBase(int oldIndex, int newIndex) | |
{ | |
base.MoveItem(oldIndex, newIndex); | |
} | |
private void SetItemBase(int index, T item) | |
{ | |
base.SetItem(index, item); | |
} | |
private void ExecuteOrInvoke(Action action) | |
{ | |
if (this.dispatcher.CheckAccess()) | |
{ | |
action(); | |
} | |
else | |
{ | |
this.dispatcher.BeginInvoke(action); | |
} | |
} | |
} |
Foreachs are not protected, while iterating the collection one can change the collection and the iteration fails.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Might be worth updating this with the BeginInvoke -> Invoke change that Ken listed on your blog:
http://www.planetgeek.ch/2011/05/17/threadsafe-observablecollection/comment-page-1/#comment-1693