Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When WaitOnNotifying is true for collections updates from other threa… #15

Merged
merged 1 commit into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,11 @@ This can be overwritten durring creation or by setting Property `WaitOnNotifyPro
Observable Collections now Wait when calling `CollectionChanged` Event.
This can be overwritten durring creation or by setting Property `WaitOnNotifyCollectionChanged`. Default value is `true`.

*(TIP: If you experience Dead Locks change this value to `false`.)*
*(TIP: If you experience Dead Locks change this value to `false`.)*


## Breaking changes from v1.0.9 to v1.0.10!

Observable Objects Property `WaitOnNotifyPropertyChanged` has been renamed to Property `WaitOnNotifying`.

Observable Collections Property `WaitOnNotifyCollectionChanged` has been removed and now uses Property `WaitOnNotifying`.
31 changes: 31 additions & 0 deletions samples/WinForms/SimpleThreadTest/SimpleThreadTest.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32127.271
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleThreadTest", "SimpleThreadTest\SimpleThreadTest.csproj", "{4E3DF2B7-56C4-4DA8-8F62-15795C1CA7BC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThunderDesign.Net-PCL.Threading", "..\..\..\src\ThunderDesign.Net-PCL.Threading\ThunderDesign.Net-PCL.Threading.csproj", "{8B8D5C7F-FA81-46BB-81B6-9245F6B8DED6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4E3DF2B7-56C4-4DA8-8F62-15795C1CA7BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E3DF2B7-56C4-4DA8-8F62-15795C1CA7BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E3DF2B7-56C4-4DA8-8F62-15795C1CA7BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E3DF2B7-56C4-4DA8-8F62-15795C1CA7BC}.Release|Any CPU.Build.0 = Release|Any CPU
{8B8D5C7F-FA81-46BB-81B6-9245F6B8DED6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B8D5C7F-FA81-46BB-81B6-9245F6B8DED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B8D5C7F-FA81-46BB-81B6-9245F6B8DED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B8D5C7F-FA81-46BB-81B6-9245F6B8DED6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {45DFC863-C602-4020-9301-9BAFD7F4DDF4}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using SimpleThreadTest.DataObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThunderDesign.Net.Threading.Collections;

namespace SimpleThreadTest.DataCollections
{
internal class ThreadTestCollection : ObservableCollectionThreadSafe<ThreadTestObject>
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using SimpleThreadTest.DataObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThunderDesign.Net.Threading.Collections;
using ThunderDesign.Net.Threading.DataCollections;

namespace SimpleThreadTest.DataCollections
{
public class ThreadTestDictionary : ObservableDataDictionary<int, ThreadTestObject>
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using SimpleThreadTest.DataObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThunderDesign.Net_PCL.Threading.Collections;

namespace SimpleThreadTest.DataCollections
{
public class ThreadTestList : ListThreadSafe<ThreadTestObject>
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThunderDesign.Net.Threading.DataObjects;
using ThunderDesign.Net.Threading.Extentions;

namespace SimpleThreadTest.DataObjects
{
public class ThreadTestObject : BindableDataObject<int>
{
#region properties
public string Name
{
get { return this.GetProperty(ref _Name, _Locker); }
set
{
//if (this.SetProperty(ref _Name, value, _Locker, true))
// OnPropertyChanged(nameof(DisplayText));
lock(_Locker)
{
if (this.SetProperty(ref _Name, value, true))
OnPropertyChanged(nameof(DisplayText));

}
}
}

public int IncCounterWaitTimeSeconds
{
get { return this.GetProperty(ref _IncCounterWaitTimeSeconds, _Locker); }
set { this.SetProperty(ref _IncCounterWaitTimeSeconds, value, _Locker, true); }
}

public int DecCounterWaitTimeSeconds
{
get { return this.GetProperty(ref _DecCounterWaitTimeSeconds, _Locker); }
set { this.SetProperty(ref _DecCounterWaitTimeSeconds, value, _Locker, true); }
}

public long Counter
{
get { return this.GetProperty(ref _Counter, _Locker); }
private set
{
if (this.SetProperty(ref _Counter, value, _Locker))
OnPropertyChanged(nameof(DisplayText));
}
}

public string DisplayText
{
get { return Name + " = " + Counter.ToString(); }
}
#endregion

#region variables
protected string _Name = String.Empty;
protected int _IncCounterWaitTimeSeconds = 1;
protected int _DecCounterWaitTimeSeconds = 1;
protected long _Counter = 0;
#endregion
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 132 additions & 0 deletions samples/WinForms/SimpleThreadTest/SimpleThreadTest/Form1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using SimpleThreadTest.DataCollections;
using SimpleThreadTest.DataObjects;
using System.Collections.Specialized;
using System.ComponentModel;
using ThunderDesign.Net.Threading.HelperClasses;

namespace SimpleThreadTest
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
//lbThreadOutput.DataSource = _ThreadTestList;
//lbThreadOutput.DisplayMember = nameof(ThreadTestObject.DisplayText);
//lbThreadOutput.ValueMember = nameof(ThreadTestObject.Id);
//lbThreadOutput.data
//lbThreadOutput.DataBind();
//lbThreadOutput.ValueMember = nameof(ThreadTestObject.Counter_AsString);
_ThreadTestCollection.CollectionChanged += OnThreadTestCollection_CollectionChanged;
}

private void OnThreadTestCollection_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var item in e.NewItems)
{
if (item is ThreadTestObject)
{
((ThreadTestObject)item).PropertyChanged += OnThreadTestObjectPropertyChanged;
}
}
OnRefreshDisplay(sender, new EventArgs());
break;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Remove:
foreach (var item in e.OldItems)
{
if (item is ThreadTestObject)
{
((ThreadTestObject)item).PropertyChanged -= OnThreadTestObjectPropertyChanged;
}
}
OnRefreshDisplay(sender, new EventArgs());
break;
case NotifyCollectionChangedAction.Replace:
break;
case NotifyCollectionChangedAction.Reset:
break;
}
}

private void OnThreadTestObjectPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (!(sender is ThreadTestObject))
return;

if (String.Equals(e.PropertyName, nameof(ThreadTestObject.DisplayText), StringComparison.OrdinalIgnoreCase))
OnRefreshDisplay(sender, new EventArgs());
}

private void OnRefreshDisplay(object? sender, EventArgs e)
{
if (lbThreadOutput.InvokeRequired)
{
//return;
lbThreadOutput.Invoke(new EventHandler(OnRefreshDisplay), sender, e);
return;
}

lbThreadOutput.DataSource = null;
lbThreadOutput.DataSource = _ThreadTestCollection;
lbThreadOutput.DisplayMember = nameof(ThreadTestObject.DisplayText);
lbThreadOutput.ValueMember = nameof(ThreadTestObject.Id);
}

private async void BtnTest_Click(object sender, EventArgs e)
{
ThreadTestObject threadTestObject = new ThreadTestObject();
threadTestObject.Id = 1;
threadTestObject.Name = "Test 1";
_ThreadTestCollection.Add(threadTestObject);

ThreadHelper.RunAndForget(() =>
{
Task.Delay(1000).GetAwaiter().GetResult();
threadTestObject.Name = "Changed";
});

//Task.Delay(5000).GetAwaiter().GetResult();

threadTestObject = new ThreadTestObject();
threadTestObject.Id = 2;
threadTestObject.Name = "Test 2";
_ThreadTestCollection.Add(threadTestObject);

ThreadHelper.RunAndForget(() =>
//Task.Run(()=>
{
ThreadTestObject threadTestObject2 = new ThreadTestObject();
threadTestObject2.Id = 3;
threadTestObject2.Name = "Test 3";
_ThreadTestCollection.Add(threadTestObject2);

threadTestObject2 = new ThreadTestObject();
threadTestObject2.Id = 4;
threadTestObject2.Name = "Test 4";
_ThreadTestCollection.Add(threadTestObject2);

threadTestObject2 = new ThreadTestObject();
threadTestObject2.Id = 5;
threadTestObject2.Name = "Test 5";
_ThreadTestCollection.Add(threadTestObject2);
});
}

//private readonly ThreadTestDictionary _ThreadTestDictionary = new ThreadTestDictionary();
//private readonly ThreadTestList _ThreadTestList = new ThreadTestList();
private readonly ThreadTestCollection _ThreadTestCollection = new ThreadTestCollection();

private void btnRefresh_Click(object sender, EventArgs e)
{
lbThreadOutput.DataSource = null;
lbThreadOutput.DataSource = _ThreadTestCollection;
lbThreadOutput.DisplayMember = nameof(ThreadTestObject.DisplayText);
lbThreadOutput.ValueMember = nameof(ThreadTestObject.Id);
}
}
}
Loading