https://github.com/thunderdesign/thunderdesign.net-pcl.threading
A combination of generic Thread-Safe objects that can be used in all application types.
https://github.com/thunderdesign/thunderdesign.net-pcl.threading
bindable binding c-sharp cross-platform csharp dotnet-core dotnet-framework dotnet-standard maui maui-app net pcl-library thread-safe thread-safety threading threadsafe thunderdesign unity xamarin xamarin-mac
Last synced: 2 months ago
JSON representation
A combination of generic Thread-Safe objects that can be used in all application types.
- Host: GitHub
- URL: https://github.com/thunderdesign/thunderdesign.net-pcl.threading
- Owner: ThunderDesign
- License: mit
- Created: 2022-02-14T01:58:48.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-07-11T06:08:22.000Z (3 months ago)
- Last Synced: 2025-07-22T10:23:05.102Z (3 months ago)
- Topics: bindable, binding, c-sharp, cross-platform, csharp, dotnet-core, dotnet-framework, dotnet-standard, maui, maui-app, net, pcl-library, thread-safe, thread-safety, threading, threadsafe, thunderdesign, unity, xamarin, xamarin-mac
- Language: C#
- Homepage:
- Size: 1.12 MB
- Stars: 3
- Watchers: 1
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# ThunderDesign.Net-PCL.Threading
[](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CI.yml)
[](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CD.yml)
[](https://www.nuget.org/packages/ThunderDesign.Net-PCL.Threading)
[](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/LICENSE)
[](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/README.md)
[](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/README.md)---
A combination of generic Thread-Safe objects for .Net development.
---
## 🚀 Now with .NET 8 support and built-in Source Generators! 🚀
> - **.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.
### Highlights include:- Collections
- CollectionThreadSafe
- DictionaryThreadSafe
- HashSetThreadSafe
- LinkedListThreadSafe
- ListThreadSafe
- ObservableCollectionThreadSafe
- ObservableDictionaryThreadSafe
- QueueThreadSafe
- SortedDictionaryThreadSafe
- SortedListThreadSafe
- StackThreadSafe
- DataCollections
- ObservableDataCollection
- ObservableDataDictionary
- DataObjects
- BindableDataObject
- DataObject
- Extentions
- IBindableObjectExtention
- INotifyCollectionChangedExtension
- INotifyPropertyChangedExtension
- ObjectExtention
- HelperClasses
- ThreadHelper
- Interfaces
- IBindableCollection
- IBindableDataObject
- IBindableDataObject\
- IBindableObject
- ICollectionThreadSafe
- IDataObject
- IDataObject\
- IDictionaryThreadSafe
- IHashSetThreadSafe
- ILinkedListThreadSafe
- IListThreadSafe
- IObservableDataCollection
- IObservableDataCollection\
- ISortedDictionaryThreadSafe
- IStackThreadSafe
- Objects
- BindableObject
- ThreadObject----
## Source Generators
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.
### What does it do?
- **Automatic Property Generation:**
The source generator scans your code for fields marked with specific attributes (such as `[BindableProperty]` or `[Property]`) and automatically generates the corresponding properties, including thread-safe accessors and `INotifyPropertyChanged` support where appropriate.
- **Interface Implementation:**
If your class does not already implement interfaces like `IBindableObject`, the generator will add the necessary interface implementations and event wiring.
- **Thread Safety:**
Generated properties use locking patterns to ensure thread safety, matching the patterns used throughout the ThunderDesign.Net-PCL.Threading library.### How to use
1. **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`.2. **Annotate your fields:**
Use `[BindableProperty]` or `[Property]` attributes on your fields to indicate which properties should be generated. The generator will handle the rest.3. **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.4. **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.
### Example Usage
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:```csharp
using ThunderDesign.Net.Threading.Attributes;public partial class Person
{
[BindableProperty]
private string _name;[Property]
private int _age;
}
```**What gets generated:**
```csharp
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:
```csharp
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).
---
### Advanced: Customizing Getter and Setter Accessors
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.#### Example
```csharp
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:**
```csharp
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`, and `setter` is `public` if not specified.**Available options for `AccessorAccessibility`:**
- `Public`
- `Private`
- `Protected`
- `Internal`
- `ProtectedInternal`
- `PrivateProtected`---
### Advanced: Notify Other Properties
You can notify other properties when a specific property changes by using the `alsoNotify` parameter in the `[BindableProperty]` attribute.
#### Example
```csharp
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:**
```csharp
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 `DisplayName` that depend on other properties.
---
### Advanced: Static Properties
The `[Property]` attribute now supports static fields, allowing you to generate thread-safe static properties with automatic locking mechanisms.
#### Example
```csharp
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:**
```csharp
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(ref T backingStore, object? lockObj = null) { /* ... */ }
public static bool SetStaticProperty(ref T backingStore, T value, object? lockObj = null) { /* ... */ }
}
```> **Note:** Static properties are only supported with the `[Property]` attribute. Use the `readonly` field modifier to create read-only static properties.
---
## Installation
Grab the latest [ThunderDesign.Net-PCL.Threading NuGet](https://www.nuget.org/packages/ThunderDesign.Net-PCL.Threading) package and install in your solution.
> Install-Package ThunderDesign.Net-PCL.Threading
Use the `-version` option to specify an [older version](https://www.nuget.org/packages/ThunderDesign.Net-PCL.Threading#versions-tab) to install.
## Examples
*(TIP: Clone repo, open the solution, build it and run sample app.)*
- Xamarin
- [SimpleContacts Example](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/tree/main/samples/Xamarin/SimpleContacts)## Please Contribute!
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](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/issues). Please check out the [How to Contribute](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/.github/CONTRIBUTING.md).
----
## Breaking changes from v1.0.7 to v1.0.8!
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`.)*
## 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`.
----