Multithreading_Library 2.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Multithreading_Library --version 2.0.0
NuGet\Install-Package Multithreading_Library -Version 2.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Multithreading_Library" Version="2.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Multithreading_Library --version 2.0.0
#r "nuget: Multithreading_Library, 2.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Multithreading_Library as a Cake Addin
#addin nuget:?package=Multithreading_Library&version=2.0.0

// Install Multithreading_Library as a Cake Tool
#tool nuget:?package=Multithreading_Library&version=2.0.0

Multithreading_Library

This library provides utilities to handle various multithreading scenarios in .NET applications. It contains the following classes:

  1. OneWriteMultiRead: This class resolves performance limitations when transferring data between threads. The main challenge with multiple readers is that they can block the writer from updating a variable, leading to contention. OneWriteMultiRead allows reader threads to access the shared data with minimal performance impact while enabling an arbitrary number of threads to read the current value simultaneously.
// Example usage
OneWrite_MultiRead<decimal> sharedDecimal = new OneWrite_MultiRead<decimal>(100);

/// Reader threads
decimal t = sharedDecimal.Value;

// Writer thread
sharedDecimal.Value = VALUE1;

Please note that for mutable and reference types it is recommended to enable DeepClone (Default) this makes objects sort of threadsafe by copying them.
Please note that each read value is then no longer Synchronized in between the threads. For immutable types such as simple data types (int, bool, ...) DeepCloning can be disabled.

Custom types and structs should implement the IDeepCloneable<T> interface when deepcopy is enabled for improved performance. Here's an example:

[Serializable]
internal class CloneableObject : IDeepCloneable<CloneableObject>
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Clothes { get; set; } = new List<string>();

    public CloneableObject DeepClone()
    {
        // Create a deep copy of the object
        var clone = new CloneableObject
        {
            Id = this.Id,
            Name = new string(this.Name.ToCharArray()) // Deep copy the string
        };
        foreach (string cloth in Clothes)
        {
            clone.Clothes.Add(new string(cloth.ToCharArray()));
        }
        return clone;
    }
}
[Serializable]
internal struct CloneableStruct : IDeepCloneable<CloneableStruct>
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> Clothes { get; set; }
    public CloneableStruct DeepClone()
    {
        // Create a deep copy of the object
        var clone = new CloneableStruct
        {
            Id = this.Id,
            Name = new string(this.Name.ToCharArray()),
            Clothes = new List<string>()
        };
        foreach (string cloth in Clothes)
        {
            clone.Clothes.Add(new string(cloth.ToCharArray()));
        }
        return clone;
    }
}

You can also access the Cloning Extension directly as suggested in the xunit test:

[Fact]
public void DeepClone_CloneableType()
{
    // Arrange
    var original = new CloneableObject()
    {
        Id = 1,
        Name = "Original",
        Clothes = new() { "Pant", "Socks" }
    };

    // Act
    var cloned = Cloning.DeepClone(original);

    // Assert
    Assert.NotNull(cloned);
    Assert.NotSame(original, cloned); // Ensure it's a different instance
    Assert.Equal(original.Id, cloned.Id);
    Assert.Equal(original.Name, cloned.Name);


    // change values to make sure we are not destroying things
    cloned.Name = "Clone";
    cloned.Id = 2;
    cloned.Clothes.AddRange(new[] { "Shirt", "Glasses" });

    // Ensure that the string is deeply copied
    Assert.NotSame(original.Name, cloned.Name);
    Assert.NotEqual(original.Id, cloned.Id);
    Assert.NotEqual(original.Name, cloned.Name);
    Assert.NotEqual(original.Clothes.Count, cloned.Clothes.Count);
}

The Cloning Method is Based on Baksteen.Extensions.DeepCopy Published under MIT-License

  1. IDLocks: This class provides locks that are accessible through a dictionary. This allows specific tasks, names, or other entities to be locked individually, enabling finer control over thread synchronization.
// Example usage
IDLocks<int> idLocks = new IDLocks<int>();
var lockObject = idLocks.ObtainLockObject(5);
  1. RequestIDGenerator this class returns an incremental, threadsafe id which can be used to identify requests. EG for a websocket. The function rolls over to 0 at int.MaxValue
// Example usage
RequestIDGenerator idGenerator = new RequestIDGenerator();
int id = idGenerator.GetNextRequestId()
  1. AsyncHelper: This class provides utilities to run an asynchronous Task and wait for the result in a synchronous method. It should be used with caution as it can lead to potential deadlocks. Whenever possible, prefer keeping async code all the way up the call stack.
// Example usage
int parameter = 5;
int result = AsyncHelper.RunSync(async () => await SomeAsyncMethod(parameter));
  1. Caching: The library includes examples of lightweight caching mechanisms.
    • LazyCache\<T\>: A simple cache that holds a value for a specified timespan. After the timespan expires, it returns null or default.

      // Example usage
      LazyCache<int?> numberCache = new (TimeSpan.FromMinutes(5)); // values are valid for 5 Minutes
      numberCache.Value = 42; // Setting a value
      int? cachedNumber = numberCache.Value; // Retrieving the value
      if (cachedNumber == null) // set new value if cache has expired
          cachedNumber = FetchReason("Life");
      
    • LazyCacheDictionary\<TKey, TValue\>: A thread-safe, lazy-loading cache dictionary with expiration for each key. It supports automatic cleanup of expired entries.

      // Example usage
      
      // individual item validity time = 5 Minutes
      // cache cleanup interval = 1 Hour
      LazyCacheDictionary<string, int?> dictionaryCache = new (TimeSpan.FromMinutes(5), TimeSpan.FromHours(1));
      
      dictionaryCache.Set("key1", 100); // Adding a value
      int? value = dictionaryCache.Get("key1"); // Retrieving a value
      if (value == null) // set new value if cache has expired
          dictionaryCache.Set("Life", 42);
      
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Multithreading_Library:

Package Downloads
Chia-Client-API

CHIA-RPC is a C# Nuget library that allows developers to easily communicate with the Chia client. It provides a wrapper for making requests, sending transactions, and minting, making it a versatile tool for interacting with the Chia blockchain. With CHIA-RPC, you can easily integrate Chia functionality into your C# projects.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.4.1 79 4/10/2024
2.4.0 72 4/9/2024
2.3.0 87 4/8/2024
2.2.0 73 4/4/2024
2.1.1 82 4/4/2024
2.1.0 86 4/4/2024
2.0.0 85 3/27/2024
1.9.0 94 3/15/2024
1.8.0 105 1/19/2024
1.7.0 57 1/19/2024
1.6.0 106 1/4/2024
1.5.0 106 12/13/2023
1.4.0 89 12/12/2023
1.3.0 106 12/5/2023
1.2.1 164 12/1/2023
1.2.0 90 12/1/2023
1.1.1 144 7/4/2023
1.1.0 132 7/4/2023
1.0.1 260 1/25/2023
1.0.0 264 1/9/2023

2.0.0
- implement new debouncers
- clean all code by fixing compiler warnings
- update xml comments

1.9.0
- added a simple cache implementation and index cache from one of my other projects

1.8.1
- Added TryGet to LazyCache

1.8.0
- implement IDReaderWriterLock

1.7.0
- Implemented IDSemaphoreSlim, simmilar to IDLocks
- Improved Documentation on IDLocks
- Improved Performance of IDLocks

1.6.0
- implement DataTransfer.ConcurrentHashset
- added unit tests
- added Ienumerable constructor for readonly hashset

1.5.0
- implement DataTransfer.ReadOnlyHashSet wrapper

1.4.0
Fully reworked OneRead_MultiWrite
- no longer nessesary to provide a timespan
- allows DeepCopy

1.3.0
- added LazyCache, a minimal cache implementation
- added LazyCacheDictionary, a minimal caching solution for dictionary values

1.2.1
- Added RequestIDGenerator to obtain short term unique identifiers
- added .Net 8.0