.NET API reference
Send ReadOnlySpan<byte> messages and receive into reusable memory. Use CancellationToken when waiting for work.
NuGet package ↗ · Public contracts ↗
Install
Requires .NET 10 or later and a 64-bit process on a supported platform.
dotnet add package Cloudtoid.Interprocess
Send and receive
using Cloudtoid.Interprocess;
var options = new QueueOptions("example", capacity: 65536);
var factory = new QueueFactory();
using var subscriber = factory.CreateSubscriber(options);
using var publisher = factory.CreatePublisher(options);
if (!publisher.TryEnqueue("hello"u8))
throw new InvalidOperationException("Queue is full or recovering");
byte[] buffer = new byte[256];
using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(1));
ReadOnlyMemory<byte> message = subscriber.Dequeue(buffer, cancellation.Token);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(message.Span));
QueueOptions
QueueOptions(string queueName, long capacity)
QueueOptions(string queueName, string path, long capacity)
Immutable queue configuration. The first overload uses Path.GetTempPath(). Windows ignores the backing path. Capacity is message-buffer bytes, greater than 16 and divisible by 8. Read-only properties are string QueueName, string Path, and long Capacity.
QueueFactory and IQueueFactory
QueueFactory() / QueueFactory(ILoggerFactory loggerFactory)
Constructs the factory with default logging or your own logger factory.
IPublisher CreatePublisher(QueueOptions options)
ISubscriber CreateSubscriber(QueueOptions options)
Create or join the transient queue as a publisher or subscriber. Both returned interfaces implement IDisposable. At most 2,048 publisher objects may be connected to a queue.
IServiceCollection AddInterprocessQueue(this IServiceCollection services)
Registers IQueueFactory with the service collection. Call services.AddInterprocessQueue() and resolve IQueueFactory through dependency injection.
IPublisher
bool TryEnqueue(ReadOnlySpan<byte> message)
Copies the bytes into shared memory without waiting for space. Returns false when the message does not fit or recovery temporarily closes admission; true means the message was committed. A notification semaphore reaching its limit does not fail an already committed send.
ISubscriber
bool TryDequeue(out ReadOnlyMemory<byte> message)
Tries once, allocating a byte array for a received message. False means no ready message, an active reader owns consumption, or the next message is unfinished.
bool TryDequeue(Memory<byte> buffer, out ReadOnlyMemory<byte> message)
Copies into your buffer. On success the returned memory references the filled part of that buffer; consume it before reusing or modifying the buffer. An undersized buffer truncates and consumes the message. A true result with zero length is a real empty message.
ReadOnlyMemory<byte> Dequeue(CancellationToken cancellation)
Blocks until a message arrives, cancellation is requested, disposal is observed, or a failure occurs. Allocates a result array. Use CancellationToken.None to wait without application cancellation.
ReadOnlyMemory<byte> Dequeue(Memory<byte> buffer, CancellationToken cancellation)
Blocking receive into caller-owned storage, with the same truncation and buffer-lifetime rules as TryDequeue with a buffer.
Failures and cancellation
Cancellation and subscriber disposal throw OperationCanceledException from receive operations. Sending through a disposed publisher throws ObjectDisposedException. Invalid options are rejected by argument validation. A publisher-limit failure throws InvalidOperationException; counter exhaustion throws OverflowException. Queue opening and access can also fail because of capacity mismatch, permissions, I/O, or invalid shared state.
False from TryEnqueue/TryDequeue is not an exception. Apply a bounded retry policy if the application needs to wait. TryDequeue has no cancellation token because it does not wait for a message.
Cleanup and concurrency
Use using for each endpoint. Disposal stops new calls and waits for admitted calls to finish before releasing resources; waiting readers observe disposal on retry. Consumption is serialized across subscribers. A stalled live participant is not treated as crashed simply because a deadline passes.
The API is synchronous; there is no DequeueAsync or batch-enqueue API. Reusing receive buffers avoids per-message result-array allocation. See queue lifetime before handing off between processes.