ParallelLanes 0.1.0

dotnet add package ParallelLanes --version 0.1.0
                    
NuGet\Install-Package ParallelLanes -Version 0.1.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="ParallelLanes" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ParallelLanes" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="ParallelLanes" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ParallelLanes --version 0.1.0
                    
#r "nuget: ParallelLanes, 0.1.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.
#:package ParallelLanes@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ParallelLanes&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=ParallelLanes&version=0.1.0
                    
Install as a Cake Tool

ParallelLanes

ParallelLanes is a lightweight lane-aware scheduler for .NET. It keeps unrelated work highly parallel while guaranteeing that items sharing the same key never overlap. Think of it as a parallel runner with automatic per-key mutexes.

Features

  • High-throughput execution with configurable worker count.
  • Per-key serialization so conflicting jobs run in order without extra plumbing.
  • First-class dependency-injection support for IServiceCollection.
  • Targets .NET 6, .NET 7, and .NET 8 (net9+ applications fall back to the net8 build).
  • Async-friendly APIs with cancellation and graceful disposal.

Installation

Once the package is published:

dotnet add package ParallelLanes

Until then, clone the repo and reference src/ParallelLanes/ParallelLanes.csproj directly.

Quick Start

using ParallelLanes;

await using var runner = new ParallelLaneRunner(new ParallelLaneRunnerOptions
{
	MaxDegreeOfParallelism = Environment.ProcessorCount
});

var work = new List<Task>
{
	runner.EnqueueAsync("alpha", async ct =>
	{
		await Task.Delay(150, ct);
	}),
	runner.EnqueueAsync("beta", async ct =>
	{
		await Task.Delay(150, ct);
	}),
	runner.EnqueueAsync("alpha", async ct =>
	{
		// Runs only after the first "alpha" item finishes.
		await Task.Delay(150, ct);
	})
};

await Task.WhenAll(work);

How It Works

  • Each queued job declares a lane key. Jobs in the same lane execute sequentially; different lanes flow in parallel.
  • The runner tracks active lanes and enqueues dependents without blocking other workers.
  • When a worker finishes a job it immediately schedules the next waiting item in that lane.
  • Cancellation tokens are honored for each queued task as well as for the runner itself.

Configuration

var options = new ParallelLaneRunnerOptions
{
	MaxDegreeOfParallelism = 4,
	LaneKeyComparer = StringComparer.OrdinalIgnoreCase
};
  • MaxDegreeOfParallelism: upper bound on concurrent workers (default: logical processor count).
  • LaneKeyComparer: comparer used to group lane keys (default: StringComparer.Ordinal).

Dependency Injection

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ParallelLanes;

var services = new ServiceCollection();

services.AddLogging(builder => builder.AddSimpleConsole());
services.AddParallelLaneRunner(options =>
{
	options.MaxDegreeOfParallelism = Math.Max(2, Environment.ProcessorCount / 2);
});

await using var provider = services.BuildServiceProvider();
await using var runner = provider.GetRequiredService<IParallelLaneRunner>();

The extension registers IParallelLaneRunner as a singleton and applies any custom options you supply.

Cancellation and Lifetime

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

var task = runner.EnqueueAsync("io", async ct =>
{
	await DoWorkAsync(ct);
}, cts.Token);

// DisposeAsync cancels queued work and waits for workers to shut down.
await runner.DisposeAsync();
  • Calling EnqueueAsync returns a task that completes when the job finishes or propagates the failure.
  • Cancel the provided token to drop queued work before it starts.
  • Disposing the runner cancels any remaining work and releases resources.

Benchmarks

Measured on an Apple M2 Pro (BenchmarkDotNet 0.14.0):

Scenario 32 items 128 items
Sequential (single lane) 73.40 ms 293.05 ms
Parallel lanes (single key) 74.39 ms 295.36 ms
Parallel lanes (mixed keys) 18.86 ms 74.38 ms
  • High contention adds ~1% overhead versus sequential execution.
  • Mixed lanes deliver ~4x throughput improvement by overlapping independent work.
  • Re-run locally with dotnet run -c Release --project tests/ParallelLanes.Benchmarks/ParallelLanes.Benchmarks.csproj -- --filter "*".

Repository Layout

  • src/ParallelLanes – main library.
  • samples/ParallelLanes.SampleApp – console demo showcasing DI and logging.
  • tests/ParallelLanes.Tests – correctness suite with xUnit.
  • tests/ParallelLanes.Benchmarks – BenchmarkDotNet scenarios.

Roadmap

  • Metrics hooks for queue depth, throughput, and idle workers.
  • Named registrations for multi-tenant or multi-runner setups.
  • Pluggable backpressure strategies and advanced scheduling policies.

Contributing

Issues and pull requests are welcome. Please open an issue describing proposed changes before submitting large PRs.

License

This project is licensed under the MIT License. See LICENSE for details.

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.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
0.1.0 115 11/7/2025