Reputation: 355
I am working on a project in which I need to notify my GUI that my list has new items.
I tried this with an observablecollection, but I use timers, and when I try to add or remove items from the observablecollection, then an exception is thrown that the collection is being marshalled from another thread.
Therefore, I started thinking about using the PropertyChanged event. However, I have trouble with getting it to work. What I understand is that it is used for properties. I have tried the following code without success:
public class MyCollection : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ConcurrentQueue<PC_Info_Item> data;
public List<string> table;
public MyCollection()
{
data = new ConcurrentQueue<PC_Info_Item>();
table = new List<string>();
}
public void Add(PC_Info_Item item)
{
data.Enqueue(item);
OnPropertyChanged(nameof(table));
}
public void Add(string item)
{
table.Add(item);
OnPropertyChanged(nameof(table));
}
public void delete()
{
data.TryDequeue(out PC_Info_Item item);
OnPropertyChanged(nameof(table));
}
public void delete_string(string item)
{
table.Remove(item);
OnPropertyChanged(nameof(table));
}
protected void OnPropertyChanged(string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Is there a way to make this work for lists?
Upvotes: 1
Views: 775
Reputation: 31
I think you should call on property changed as below where we should get the invocation list and call invoke on each receiver with lock.
private object _lock = new object();
protected void OnPropertyChanged(string name = "")
{
var receivers = this.PropertyChanged.GetInvocationList();
foreach (EventHandler<PropertyChangedEventArgs> receiver in receivers)
{
lock (this._lock)
{
receiver?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
Upvotes: 1
Reputation: 229
you can wrap the calls into lock, that will make other threads wait till the call is finished.
private readonly object CollectionLock = new object();
public void Add(PC_Info_Item item)
{
lock(CollectionLock) {
data.Enqueue(item);
}
}
public void Add(string item)
{
lock(CollectionLock) {
table.Add(item);
}
}
public void delete()
{
lock(CollectionLock) {
data.TryDequeue(out PC_Info_Item item);
}
}
public void delete_string(string item)
{
lock(CollectionLock) {
table.Remove(item);
}
}
Upvotes: 1