VanLangen.Locking.ReadersWriterLockAsync 1.0.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package VanLangen.Locking.ReadersWriterLockAsync --version 1.0.4                
NuGet\Install-Package VanLangen.Locking.ReadersWriterLockAsync -Version 1.0.4                
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="VanLangen.Locking.ReadersWriterLockAsync" Version="1.0.4" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add VanLangen.Locking.ReadersWriterLockAsync --version 1.0.4                
#r "nuget: VanLangen.Locking.ReadersWriterLockAsync, 1.0.4"                
#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 VanLangen.Locking.ReadersWriterLockAsync as a Cake Addin
#addin nuget:?package=VanLangen.Locking.ReadersWriterLockAsync&version=1.0.4

// Install VanLangen.Locking.ReadersWriterLockAsync as a Cake Tool
#tool nuget:?package=VanLangen.Locking.ReadersWriterLockAsync&version=1.0.4                

ReadersWriterLockAsync

ReadersWriterLockAsync solves the thread affinity problem for using multiple readers and a single writer lock using async code.

This version is not released yet i'm still working on some tests

Examples:

The Write function adds some stopwatch time to the output

Async example:

Write("Before calling UseReaderAsync");
var result = _readersWriterLock.UseReaderAsync(async () =>
{
    Write("Reader start");
    await Task.Delay(1000);
    Write("Reader end");
});
Write("After calling UseReaderAsync");

if (!result.IsCompleted)
{
    Write("result.IsCompleted == false, awaiting");
    await result;
    Write("awaiting ready");
}
else
    Write("result.IsCompleted == true");

Output:

      21,078 ms | Before calling UseReaderAsync
      51,063 ms | Reader start
      70,050 ms | After calling UseReaderAsync
      70,193 ms | result.IsCompleted == false, awaiting
   1.083,426 ms | Reader end
   1.083,705 ms | awaiting ready

As you can see the "Reader start" is executed directly. Because of the await, the result.IsComplete is not set. We're able to await the result.

Non async example:

Write("Before calling UseReaderAsync");
var result = _readersWriterLock.UseReaderAsync(() =>
{
    Write("Reader start");
    // await Task.Delay(1000);
    Write("Reader end");
});
Write("After calling UseReaderAsync");

if (!result.IsCompleted)
{
    Write("result.IsCompleted == false, awaiting");
    await result;
    Write("awaiting ready");
}
else
    Write("result.IsCompleted == true");

Output:

      19,983 ms | Before calling UseReaderAsync
      46,000 ms | Reader start
      46,100 ms | Reader end
      46,625 ms | After calling UseReaderAsync
      46,666 ms | result.IsCompleted == true

Here no await is used and the method completes directly. No await is needed, which speeds-up the system.

Some readers and writers

Let's add two readers and then two writers followed by a reader. The expected behavior should be:

  1. reader A and B should run parallel
  2. writer C
  3. writer D
  4. reader E
// Initialize an array with some readers and writers.
var allValueTasks = new[]
{
    // the first reader will run directly
    _readersWriterLock.UseReaderAsync(async () =>
    {
        Write("Reader A start");
        await Task.Delay(1000);
        Write("Reader A end");
    }),
    // the second reader will also run directly
    _readersWriterLock.UseReaderAsync(async () =>
    {
        Write("Reader B start");
        await Task.Delay(1000);
        Write("Reader B end");
    }),
    // because of two readers, this writer has to be queued
    _readersWriterLock.UseWriterAsync(async () =>
    {
        Write("Writer C start");
        await Task.Delay(1000);
        Write("Writer C end");
    }),
    // because of two readers and a writer queued, this writer has to be queued also
    _readersWriterLock.UseWriterAsync(async () =>
    {
        Write("Writer D start");
        await Task.Delay(1000);
        Write("Writer D end");
    }),
    // Lets add another reader, because some writers are queued, this reader is queued also
    _readersWriterLock.UseReaderAsync(async () =>
    {
        Write("Reader E start");
        await Task.Delay(1000);
        Write("Reader E end");
    }),
};

foreach (var valueTask in allValueTasks)
    if (!valueTask.IsCompleted)
        await valueTask;
}

Output:

      23,056 ms | Reader A start
      53,059 ms | Reader B start
   1.073,641 ms | Reader B end
   1.073,820 ms | Reader A end
   1.078,123 ms | Writer C start
   2.086,785 ms | Writer C end
   2.087,468 ms | Writer D start
   3.096,612 ms | Writer D end
   3.097,310 ms | Reader E start
   4.102,154 ms | Reader E end
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  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 was computed.  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 was computed.  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.
  • net5.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.11 25,594 12/11/2020
1.0.10 385 12/10/2020
1.0.9 410 12/8/2020
1.0.8 390 12/7/2020
1.0.7 405 12/7/2020
1.0.6 420 12/6/2020
1.0.5 412 12/6/2020
1.0.4 429 12/6/2020
1.0.3 480 12/6/2020
1.0.2 397 12/6/2020
1.0.1 399 12/6/2020
1.0.0 407 12/6/2020