![]() |
VOOZH | about |
dotnet add package ThunderDesign.Net-PCL.Threading --version 2.2.0
NuGet\Install-Package ThunderDesign.Net-PCL.Threading -Version 2.2.0
<PackageReference Include="ThunderDesign.Net-PCL.Threading" Version="2.2.0" />
<PackageVersion Include="ThunderDesign.Net-PCL.Threading" Version="2.2.0" />Directory.Packages.props
<PackageReference Include="ThunderDesign.Net-PCL.Threading" />Project file
paket add ThunderDesign.Net-PCL.Threading --version 2.2.0
#r "nuget: ThunderDesign.Net-PCL.Threading, 2.2.0"
#:package ThunderDesign.Net-PCL.Threading@2.2.0
#addin nuget:?package=ThunderDesign.Net-PCL.Threading&version=2.2.0Install as a Cake Addin
#tool nuget:?package=ThunderDesign.Net-PCL.Threading&version=2.2.0Install as a Cake Tool
π CI
π CD
π Nuget
π License
π NetStandard
π Net
A combination of generic Thread-Safe objects for .Net development.
- .NET 8: Take advantage of the latest .NET features and performance improvements.
- Source Generators: Eliminate boilerplate and let the library generate thread-safe, bindable properties for you automatically!
Get started faster, write less code, and enjoy modern .NET development!
A simple C# repository containing a few basic useful Thread-Safe Objects.
The ThunderDesign.Net-PCL.Threading project provides Roslyn-based source generators that automate the creation of common boilerplate code for thread-safe and bindable objects in this library. By including this package in your project, you can reduce repetitive code and ensure consistency across your data and collection classes.
[BindableProperty] or [Property]) and automatically generates the corresponding properties, including thread-safe accessors and INotifyPropertyChanged support where appropriate.IBindableObject, the generator will add the necessary interface implementations and event wiring.Add the NuGet package:
Reference the ThunderDesign.Net-PCL.Threading package in your project. If you are building from source, add a project reference to ThunderDesign.Net-PCL.SourceGenerators.csproj.
Annotate your fields:
Use [BindableProperty] or [Property] attributes on your fields to indicate which properties should be generated. The generator will handle the rest.
Build your project:
When you build, the source generator will automatically add the generated code to your compilation. You do not need to manually include or maintain the generated files.
Enjoy less boilerplate:
Your classes will have all the necessary properties, events, and thread-safety mechanisms without manual implementation.
Note: Source generators require Visual Studio 2019 16.9+ or .NET SDK 5.0+ for full support.
Suppose you want to create a thread-safe, bindable object with automatic property and notification support.
With the source generator, you only need to annotate your fields:
using ThunderDesign.Net.Threading.Attributes;
public partial class Person
{
[BindableProperty]
private string _name;
[Property]
private int _age;
}
What gets generated:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using ThunderDesign.Net.Threading.Extentions;
using ThunderDesign.Net.Threading.Interfaces;
public partial class Person : IBindableObject, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected readonly object _Locker = new object();
public string Name
{
get { return this.GetProperty(ref _name, _Locker); }
set { this.SetProperty(ref _name, value, _Locker, true); }
}
public int Age
{
get { return this.GetProperty(ref _age, _Locker); }
set { this.SetProperty(ref _age, value, _Locker); }
}
}
You can now use your Person class like this:
var person = new Person();
person.Name = "Alice";
person.Age = 30;
// PropertyChanged event will be raised for Name changes if you subscribe to it.
No need to manually implement property notification, thread safety, or boilerplate codeβthe generator does it for you!
For more advanced scenarios, you can use attribute parameters to control property behavior (e.g., read-only, also notify other properties, or control accessor/property visibility).
You can control the visibility of the generated property's getter and setter using the AccessorAccessibility enum.
The property itself will use the most accessible (widest) of the getter or setter's accessibilities.
using ThunderDesign.Net.Threading.Attributes;
using ThunderDesign.Net.Threading.Enums;
public partial class Person
{
// Public getter, private setter (property will be public)
[BindableProperty(getter: AccessorAccessibility.Public, setter: AccessorAccessibility.Private)]
private string _name;
// Internal getter, protected setter (property will be internal)
[Property(getter: AccessorAccessibility.Internal, setter: AccessorAccessibility.Protected)]
private int _age;
}
What gets generated:
public partial class Person
{
public string Name
{
get { return this.GetProperty(ref _name, _Locker); }
private set { this.SetProperty(ref _name, value, _Locker, true); }
}
internal int Age
{
internal get { return this.GetProperty(ref _age, _Locker); }
protected set { this.SetProperty(ref _age, value, _Locker); }
}
}
The property will be as accessible as its most accessible accessor (getter or setter). The default for
getter, andsetterispublicif not specified.
Available options for AccessorAccessibility:
PublicPrivateProtectedInternalProtectedInternalPrivateProtectedYou can notify other properties when a specific property changes by using the alsoNotify parameter in the [BindableProperty] attribute.
using ThunderDesign.Net.Threading.Attributes;
public partial class Person
{
[BindableProperty(alsoNotify: new[] { nameof(DisplayName) })]
private string _firstName;
[BindableProperty(alsoNotify: new[] { nameof(DisplayName) })]
private string _lastName;
public string DisplayName => $"{FirstName} {LastName}";
}
What gets generated:
public partial class Person : IBindableObject, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected readonly object _Locker = new object();
public string FirstName
{
get { return this.GetProperty(ref _firstName, _Locker); }
set
{
if (this.SetProperty(ref _firstName, value, _Locker, true))
{
this.OnPropertyChanged(nameof(DisplayName));
}
}
}
public string LastName
{
get { return this.GetProperty(ref _lastName, _Locker); }
set
{
if (this.SetProperty(ref _lastName, value, _Locker, true))
{
this.OnPropertyChanged(nameof(DisplayName));
}
}
}
public string DisplayName => $"{FirstName} {LastName}";
}
This feature is particularly useful for computed properties like
DisplayNamethat depend on other properties.
The [Property] attribute now supports static fields, allowing you to generate thread-safe static properties with automatic locking mechanisms.
using ThunderDesign.Net.Threading.Attributes;
public partial class AppSettings
{
[Property]
private static string _applicationName = "MyApp";
[Property(getter: AccessorAccessibility.Internal)]
private static readonly string _version = "1.0.0";
}
What gets generated:
public partial class AppSettings
{
static readonly object _StaticLocker = new object();
public static string ApplicationName
{
get { return GetStaticProperty(ref _applicationName, _StaticLocker); }
set { SetStaticProperty(ref _applicationName, value, _StaticLocker); }
}
internal static string Version
{
get { return GetStaticProperty(ref _version, _StaticLocker); }
}
// Helper methods for static property access
public static T GetStaticProperty<T>(ref T backingStore, object? lockObj = null) { /* ... */ }
public static bool SetStaticProperty<T>(ref T backingStore, T value, object? lockObj = null) { /* ... */ }
}
Note: Static properties are only supported with the
[Property]attribute. Use thereadonlyfield modifier to create read-only static properties.
Grab the latest ThunderDesign.Net-PCL.Threading NuGet package and install in your solution.
Install-Package ThunderDesign.Net-PCL.Threading
Use the -version option to specify an older version to install.
(TIP: Clone repo, open the solution, build it and run sample app.)
This is an open source project that welcomes contributions/suggestions/bug reports from those who use it. If you have any ideas on how to improve the library, please post an issue here on GitHub. Please check out the How to Contribute.
Observable Objects now Wait when calling PropertyChanged Event.
This can be overwritten durring creation or by setting Property WaitOnNotifyPropertyChanged. Default value is true.
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.)
Observable Objects Property WaitOnNotifyPropertyChanged has been renamed to Property WaitOnNotifying.
WaitOnNotifyCollectionChanged has been removed and now uses Property WaitOnNotifying.| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 is compatible. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp1.0 netcoreapp1.0 was computed. netcoreapp1.1 netcoreapp1.1 was computed. netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard1.0 netstandard1.0 is compatible. netstandard1.1 netstandard1.1 was computed. netstandard1.2 netstandard1.2 was computed. netstandard1.3 netstandard1.3 is compatible. netstandard1.4 netstandard1.4 was computed. netstandard1.5 netstandard1.5 was computed. netstandard1.6 netstandard1.6 was computed. netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net45 net45 was computed. net451 net451 was computed. net452 net452 was computed. net46 net46 was computed. net461 net461 is compatible. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen30 tizen30 was computed. tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Universal Windows Platform | uap uap was computed. uap10.0 uap10.0 was computed. |
| Windows Phone | wp8 wp8 was computed. wp81 wp81 was computed. wpa81 wpa81 was computed. |
| Windows Store | netcore netcore was computed. netcore45 netcore45 was computed. netcore451 netcore451 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 4 NuGet packages that depend on ThunderDesign.Net-PCL.Threading:
| Package | Downloads |
|---|---|
|
ThunderDesign.Net-PCL.SQLite
A wrapper around the popular 'sqlite-net-pcl' automating the reading and writing to the database through simple thread-safe bindable objects. |
|
|
ThunderDesign.Net-PCL.Dynamic
A combination of generic Dynamic Thread-Safe objects that can be used in all application types. |
|
|
ThunderDesign.Net-PCL.HttpClientService
A wrapper around 'System.Net.Http.HttpClient' enhancing AutoRedirect and Cookies. Can be used in all application types. |
|
|
ThunderDesign.Xamarin.Forms.FloatingActionButton
FloatingActionButton (FAB) with custom shadow (Color, Offset, Blur) and custom Animation Easing (Show, Hide) for Xamarin.Forms view (Android, iOS, UWP) |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.2.0 | 799 | 7/11/2025 |
| 2.1.0 | 348 | 6/25/2025 |
| 2.0.1 | 234 | 6/21/2025 |
| 2.0.0 | 313 | 6/19/2025 |
| 1.0.10 | 1,592 | 10/13/2023 |
| 1.0.9 | 397 | 9/6/2023 |
| 1.0.8 | 247 | 9/5/2023 |
| 1.0.7 | 1,346 | 10/28/2022 |
| 1.0.6 | 2,669 | 3/21/2022 |
| 1.0.5 | 1,878 | 3/2/2022 |
| 1.0.4 | 611 | 3/2/2022 |
| 1.0.3 | 896 | 2/23/2022 |
| 1.0.2 | 914 | 2/21/2022 |
| 1.0.1 | 629 | 2/19/2022 |
| 1.0.0 | 1,175 | 2/14/2022 |