SelectorQueue 1.0.0
dotnet add package SelectorQueue --version 1.0.0
NuGet\Install-Package SelectorQueue -Version 1.0.0
<PackageReference Include="SelectorQueue" Version="1.0.0" />
<PackageVersion Include="SelectorQueue" Version="1.0.0" />
<PackageReference Include="SelectorQueue" />
paket add SelectorQueue --version 1.0.0
#r "nuget: SelectorQueue, 1.0.0"
#:package SelectorQueue@1.0.0
#addin nuget:?package=SelectorQueue&version=1.0.0
#tool nuget:?package=SelectorQueue&version=1.0.0
SelectorQueue
<p align="center"> <img src="https://raw.githubusercontent.com/jchristn/selectorqueue/main/assets/icon.png" alt="SelectorQueue icon" width="256" height="256" /> </p>
SelectorQueue is a thread-safe, stable ordered queue for .NET. It accepts items in nondeterministic arrival order and dequeues them in a frozen sort order defined up front through a builder.
What Changed
Version 1.0.0 ships with:
- a binary heap instead of sorted-list insertion/removal
- immutable ordering configuration built before queue use
- stable ordering via an internal sequence tiebreaker
- a reduced public API focused on core queue behavior
Usage
using SelectorQueue;
public sealed class CallRecording
{
public string Key { get; init; } = string.Empty;
public long Size { get; init; }
public DateTime Timestamp { get; init; }
}
SelectorQueue<CallRecording> queue = SelectorQueue
.OrderBy<CallRecording, DateTime>(x => x.Timestamp)
.ThenByDescending<long>(x => x.Size)
.ThenBy<string>(x => x.Key)
.Build();
queue.Enqueue(new CallRecording { Key = "call_003.wav", Size = 50_000, Timestamp = DateTime.Parse("2025-06-15T14:00:00Z") });
queue.Enqueue(new CallRecording { Key = "call_001.wav", Size = 30_000, Timestamp = DateTime.Parse("2025-06-15T12:00:00Z") });
queue.Enqueue(new CallRecording { Key = "call_002.wav", Size = 40_000, Timestamp = DateTime.Parse("2025-06-15T13:00:00Z") });
while (queue.TryDequeue(out CallRecording recording))
{
Console.WriteLine($"{recording.Key} {recording.Timestamp:o} {recording.Size}");
}
If you do not need explicit ordering, use SelectorQueue.Create<T>() for a FIFO queue.
IDisposable Example
using SelectorQueue;
public sealed class WorkItem : IDisposable
{
public WorkItem(string name, int priority)
{
Name = name;
Priority = priority;
}
public string Name { get; }
public int Priority { get; }
public void Dispose()
{
Console.WriteLine("Disposed " + Name);
}
}
using SelectorQueue<WorkItem> queue = SelectorQueue
.OrderBy<WorkItem, int>(x => x.Priority)
.Build();
queue.Enqueue(new WorkItem("low", 10));
queue.Enqueue(new WorkItem("high", 1));
WorkItem next = queue.Dequeue();
try
{
Console.WriteLine("Processing " + next.Name);
}
finally
{
next.Dispose();
}
// Any remaining queued WorkItem instances are disposed automatically
// when the queue is cleared or disposed.
Supported API
Ordering is configured on SelectorQueueBuilder<T> and frozen when Build() is called.
OrderByOrderByDescendingThenByThenByDescendingBuild
Queue operations are exposed on SelectorQueue<T>.
EnqueueDequeueTryDequeuePeekTryPeekCountClearDispose
Contract
EnqueueisO(log n).DequeueisO(log n).PeekisO(1).- Equal ordering keys preserve enqueue order.
- The queue owns items while they remain enqueued.
Clear()removes queued items but keeps the queue's ordering configuration for its lifetime.Clear()disposes queued values that implementIDisposable.Dispose()disposes queued values that implementIDisposableand permanently closes the queue.- After
Dispose(), all queue operations throwObjectDisposedException. Dequeue()and successfulTryDequeue()transfer ownership of the returned item back to the caller.- Empty
Dequeue()andPeek()throwInvalidOperationException. - Empty
TryDequeue()andTryPeek()returnfalseand set the out value todefault. - Selector delegates run before insertion. If a selector throws during
Enqueue, the queue is unchanged. - Null keys follow
Comparer<TKey>.Defaultsemantics. For reference and nullable types, null sorts before non-null in ascending order.
Thread Safety
All queue operations are linearizable and safe for concurrent producers and consumers. Heap mutation occurs inside a single lock.
Framework
The package targets net8.0 and net10.0.
Version History
See CHANGELOG.md.
Attribution
Icon attribution: https://www.flaticon.com/free-icon/sort_306422
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 is compatible. 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. |
-
net10.0
- No dependencies.
-
net8.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.0 | 459 | 3/18/2026 |
Initial release