{"id":29672649,"url":"https://github.com/thunderdesign/thunderdesign.net-pcl.threading","last_synced_at":"2025-07-22T21:06:59.518Z","repository":{"id":43067522,"uuid":"458984182","full_name":"ThunderDesign/ThunderDesign.Net-PCL.Threading","owner":"ThunderDesign","description":"A combination of generic Thread-Safe objects that can be used in all application types.","archived":false,"fork":false,"pushed_at":"2025-07-11T06:08:22.000Z","size":1171,"stargazers_count":3,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-22T10:23:05.102Z","etag":null,"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"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThunderDesign.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-02-14T01:58:48.000Z","updated_at":"2025-07-12T08:21:39.000Z","dependencies_parsed_at":"2023-10-14T17:10:58.066Z","dependency_job_id":"62ad48c7-9690-4cb3-99f4-07a55e483b18","html_url":"https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/ThunderDesign/ThunderDesign.Net-PCL.Threading","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThunderDesign%2FThunderDesign.Net-PCL.Threading","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThunderDesign%2FThunderDesign.Net-PCL.Threading/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThunderDesign%2FThunderDesign.Net-PCL.Threading/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThunderDesign%2FThunderDesign.Net-PCL.Threading/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThunderDesign","download_url":"https://codeload.github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThunderDesign%2FThunderDesign.Net-PCL.Threading/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266572778,"owners_count":23950092,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["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"],"created_at":"2025-07-22T21:06:58.777Z","updated_at":"2025-07-22T21:06:59.500Z","avatar_url":"https://github.com/ThunderDesign.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# ThunderDesign.Net-PCL.Threading\n[![CI](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CI.yml/badge.svg)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CI.yml)\n[![CD](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CD.yml/badge.svg)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/actions/workflows/CD.yml)\n[![Nuget](https://img.shields.io/nuget/v/ThunderDesign.Net-PCL.Threading)](https://www.nuget.org/packages/ThunderDesign.Net-PCL.Threading)\n[![License](https://img.shields.io/github/license/ThunderDesign/ThunderDesign.Net-PCL.Threading)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/LICENSE)\n[![NetStandard](https://img.shields.io/badge/.net%20standard-v1.0%20--%20v2.1-blue)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/README.md)\n[![Net](https://img.shields.io/badge/.net%20-v6.0%20--%20v8.0-blue)](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/blob/main/README.md)\n\n---\n\nA combination of generic Thread-Safe objects for .Net development.\n\n---\n\n## 🚀 Now with .NET 8 support and built-in Source Generators! 🚀\n\n\u003e - **.NET 8**: Take advantage of the latest .NET features and performance improvements.  \n\u003e - **Source Generators**: Eliminate boilerplate and let the library generate thread-safe, bindable properties for you automatically!  \n\u003e  \n\u003e _Get started faster, write less code, and enjoy modern .NET development!_\n\n----\n\nA simple C# repository containing a few basic useful Thread-Safe Objects.\n### Highlights include:\n\n- Collections\n  - CollectionThreadSafe\n  - DictionaryThreadSafe\n  - HashSetThreadSafe\n  - LinkedListThreadSafe\n  - ListThreadSafe\n  - ObservableCollectionThreadSafe\n  - ObservableDictionaryThreadSafe\n  - QueueThreadSafe\n  - SortedDictionaryThreadSafe\n  - SortedListThreadSafe\n  - StackThreadSafe\n- DataCollections\n  - ObservableDataCollection\n  - ObservableDataDictionary\n- DataObjects\n  - BindableDataObject\n  - DataObject\n- Extentions\n  - IBindableObjectExtention\n  - INotifyCollectionChangedExtension\n  - INotifyPropertyChangedExtension\n  - ObjectExtention\n- HelperClasses\n  - ThreadHelper\n- Interfaces\n  - IBindableCollection\n  - IBindableDataObject\n  - IBindableDataObject\\\u003cKey\u003e\n  - IBindableObject\n  - ICollectionThreadSafe\n  - IDataObject\n  - IDataObject\\\u003cKey\u003e\n  - IDictionaryThreadSafe\n  - IHashSetThreadSafe\n  - ILinkedListThreadSafe\n  - IListThreadSafe\n  - IObservableDataCollection\n  - IObservableDataCollection\\\u003cT\u003e\n  - ISortedDictionaryThreadSafe\n  - IStackThreadSafe\n- Objects\n  - BindableObject\n  - ThreadObject\n\n----\n\n## Source Generators\n\nThe `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.\n\n### What does it do?\n\n- **Automatic Property Generation:**  \n  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.\n- **Interface Implementation:**  \n  If your class does not already implement interfaces like `IBindableObject`, the generator will add the necessary interface implementations and event wiring.\n- **Thread Safety:**  \n  Generated properties use locking patterns to ensure thread safety, matching the patterns used throughout the ThunderDesign.Net-PCL.Threading library.\n\n### How to use\n\n1. **Add the NuGet package:**  \n   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`.\n\n2. **Annotate your fields:**  \n   Use `[BindableProperty]` or `[Property]` attributes on your fields to indicate which properties should be generated. The generator will handle the rest.\n\n3. **Build your project:**  \n   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.\n\n4. **Enjoy less boilerplate:**  \n   Your classes will have all the necessary properties, events, and thread-safety mechanisms without manual implementation.\n\n\u003e **Note:** Source generators require Visual Studio 2019 16.9+ or .NET SDK 5.0+ for full support.\n\n### Example Usage\n\nSuppose you want to create a thread-safe, bindable object with automatic property and notification support.  \nWith the source generator, you only need to annotate your fields:\n\n```csharp\nusing ThunderDesign.Net.Threading.Attributes;\n\npublic partial class Person \n{\n    [BindableProperty]\n    private string _name;\n\n    [Property]\n    private int _age;\n}\n```\n\n**What gets generated:**\n\n```csharp\nusing System.ComponentModel;\nusing System.Runtime.CompilerServices;\nusing ThunderDesign.Net.Threading.Extentions;\nusing ThunderDesign.Net.Threading.Interfaces;\n\npublic partial class Person : IBindableObject, INotifyPropertyChanged\n{\n    public event PropertyChangedEventHandler PropertyChanged;\n    protected readonly object _Locker = new object();\n\n    public string Name\n    {\n        get { return this.GetProperty(ref _name, _Locker); }\n        set { this.SetProperty(ref _name, value, _Locker, true); }\n    }\n\n    public int Age\n    {\n        get { return this.GetProperty(ref _age, _Locker); }\n        set { this.SetProperty(ref _age, value, _Locker); }\n    }\n}\n```\n\nYou can now use your `Person` class like this:\n\n```csharp\nvar person = new Person();\nperson.Name = \"Alice\";\nperson.Age = 30;\n// PropertyChanged event will be raised for Name changes if you subscribe to it.\n```\n\n**No need to manually implement** property notification, thread safety, or boilerplate code—the generator does it for you!\n\n\u003e 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).\n\n---\n\n### Advanced: Customizing Getter and Setter Accessors\n\nYou can control the visibility of the generated property's getter and setter using the `AccessorAccessibility` enum.  \nThe property itself will use the most accessible (widest) of the getter or setter's accessibilities.\n\n#### Example\n\n```csharp\nusing ThunderDesign.Net.Threading.Attributes;\nusing ThunderDesign.Net.Threading.Enums;\n\npublic partial class Person\n{\n    // Public getter, private setter (property will be public)\n    [BindableProperty(getter: AccessorAccessibility.Public, setter: AccessorAccessibility.Private)]\n    private string _name;\n\n    // Internal getter, protected setter (property will be internal)\n    [Property(getter: AccessorAccessibility.Internal, setter: AccessorAccessibility.Protected)]\n    private int _age;\n}\n```\n\n**What gets generated:**\n```csharp\npublic partial class Person\n{\n    public string Name\n    {\n        get { return this.GetProperty(ref _name, _Locker); }\n        private set { this.SetProperty(ref _name, value, _Locker, true); }\n    }\n\n    internal int Age\n    {\n        internal get { return this.GetProperty(ref _age, _Locker); }\n        protected set { this.SetProperty(ref _age, value, _Locker); }\n    }\n}\n\n```\n\n\u003e The property will be as accessible as its most accessible accessor (getter or setter).\n\u003e The default for `getter`, and `setter` is `public` if not specified.\n\n**Available options for `AccessorAccessibility`:**\n- `Public`\n- `Private`\n- `Protected`\n- `Internal`\n- `ProtectedInternal`\n- `PrivateProtected`\n\n---\n\n### Advanced: Notify Other Properties\n\nYou can notify other properties when a specific property changes by using the `alsoNotify` parameter in the `[BindableProperty]` attribute.\n\n#### Example\n```csharp\nusing ThunderDesign.Net.Threading.Attributes;\n\npublic partial class Person\n{\n    [BindableProperty(alsoNotify: new[] { nameof(DisplayName) })]\n    private string _firstName;\n\n    [BindableProperty(alsoNotify: new[] { nameof(DisplayName) })]\n    private string _lastName;\n\n    public string DisplayName =\u003e $\"{FirstName} {LastName}\";\n}\n```\n\n**What gets generated:**\n\n```csharp\npublic partial class Person : IBindableObject, INotifyPropertyChanged\n{\n    public event PropertyChangedEventHandler PropertyChanged;\n    protected readonly object _Locker = new object();\n\n    public string FirstName\n    {\n        get { return this.GetProperty(ref _firstName, _Locker); }\n        set\n        {\n            if (this.SetProperty(ref _firstName, value, _Locker, true))\n            {\n                this.OnPropertyChanged(nameof(DisplayName));\n            }\n        }\n    }\n\n    public string LastName\n    {\n        get { return this.GetProperty(ref _lastName, _Locker); }\n        set\n        {\n            if (this.SetProperty(ref _lastName, value, _Locker, true))\n            {\n                this.OnPropertyChanged(nameof(DisplayName));\n            }\n        }\n    }\n\n    public string DisplayName =\u003e $\"{FirstName} {LastName}\";\n}\n```\n\n\u003e This feature is particularly useful for computed properties like `DisplayName` that depend on other properties.\n\n---\n\n### Advanced: Static Properties\n\nThe `[Property]` attribute now supports static fields, allowing you to generate thread-safe static properties with automatic locking mechanisms.\n\n#### Example\n```csharp\nusing ThunderDesign.Net.Threading.Attributes;\n\npublic partial class AppSettings\n{\n    [Property]\n    private static string _applicationName = \"MyApp\";\n\n    [Property(getter: AccessorAccessibility.Internal)]\n    private static readonly string _version = \"1.0.0\";\n}\n```\n\n**What gets generated:**\n\n```csharp\npublic partial class AppSettings\n{ \n    static readonly object _StaticLocker = new object();\n\n    public static string ApplicationName\n    {\n        get { return GetStaticProperty(ref _applicationName, _StaticLocker); }\n        set { SetStaticProperty(ref _applicationName, value, _StaticLocker); }\n    }\n\n    internal static string Version\n    {\n        get { return GetStaticProperty(ref _version, _StaticLocker); }\n    }\n\n    // Helper methods for static property access\n    public static T GetStaticProperty\u003cT\u003e(ref T backingStore, object? lockObj = null) { /* ... */ }\n    public static bool SetStaticProperty\u003cT\u003e(ref T backingStore, T value, object? lockObj = null) { /* ... */ }\n}\n```\n\n\u003e **Note:** Static properties are only supported with the `[Property]` attribute. Use the `readonly` field modifier to create read-only static properties.\n\n---\n\n## Installation\n\nGrab the latest [ThunderDesign.Net-PCL.Threading NuGet](https://www.nuget.org/packages/ThunderDesign.Net-PCL.Threading) package and install in your solution.\n\n\u003e Install-Package ThunderDesign.Net-PCL.Threading\n\nUse the `-version` option to specify an [older version](https://www.nuget.org/packages/ThunderDesign.Net-PCL.Threading#versions-tab) to install.\n\n## Examples\n\n*(TIP: Clone repo, open the solution, build it and run sample app.)*\n- Xamarin\n  - [SimpleContacts Example](https://github.com/ThunderDesign/ThunderDesign.Net-PCL.Threading/tree/main/samples/Xamarin/SimpleContacts)\n\n## Please Contribute!\n\nThis 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).\n\n----\n\n## Breaking changes from v1.0.7 to v1.0.8!\n\nObservable Objects now Wait when calling `PropertyChanged` Event.\nThis can be overwritten durring creation or by setting Property `WaitOnNotifyPropertyChanged`. Default value is `true`.\n\nObservable Collections now Wait when calling `CollectionChanged` Event.\nThis can be overwritten durring creation or by setting Property `WaitOnNotifyCollectionChanged`. Default value is `true`.\n\n*(TIP: If you experience Dead Locks change this value to `false`.)*\n\n\n## Breaking changes from v1.0.9 to v1.0.10!\n\nObservable Objects Property `WaitOnNotifyPropertyChanged` has been renamed to Property `WaitOnNotifying`.\n\nObservable Collections Property `WaitOnNotifyCollectionChanged` has been removed and now uses Property `WaitOnNotifying`.\n----\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthunderdesign%2Fthunderdesign.net-pcl.threading","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthunderdesign%2Fthunderdesign.net-pcl.threading","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthunderdesign%2Fthunderdesign.net-pcl.threading/lists"}