Skip to content

Quickstart

Mark Lauter edited this page Jun 15, 2026 · 1 revision

Quickstart

This walks you through a working pool end to end: register it, inject it, lease an item, and return it. By the end you have the whole lease/release contract in hand. It assumes you have installed MSL.Pool and target .NET 10.

The example pools an SmtpConnection — an object that is expensive to construct and safe to reuse, which is exactly what a pool is for.

Register a pool

Register the pool against your service collection. The default factory constructs items from the service provider, so register the item type as well:

using Pool;

services.AddTransient<SmtpConnection>();   // the default factory resolves items from DI
services.AddPool<SmtpConnection>(configuration, options =>
{
    options.MinSize = 2;                   // pre-create two on startup
    options.MaxSize = 10;                  // never more than ten at once
    options.UseDefaultFactory = true;      // construct items from the service provider
});

MinSize items are created when the pool is built; MaxSize is the hard ceiling on how many exist at once. The Pool options reference lists every setting.

Lease and release an item

Inject IPool<SmtpConnection> and lease an item with LeaseAsync. Return it with Release from a finally, so the item goes back even when the work throws:

public sealed class Mailer(IPool<SmtpConnection> pool)
{
    public async Task SendAsync(Message message)
    {
        var connection = await pool.LeaseAsync();
        try
        {
            await connection.SendAsync(message);
        }
        finally
        {
            pool.Release(connection);      // always release, exactly once
        }
    }
}

That is the whole contract: LeaseAsync to borrow, Release to return.

Prefer a scoped lease

Writing the try/finally by hand is the part you can forget. LeaseScopeAsync wraps the lease in a disposable, so a using returns the item on scope exit:

using var lease = await pool.LeaseScopeAsync(cancellationToken);
await lease.Item.SendAsync(message, cancellationToken);

This is the recommended way to lease. It turns "forgot to release" — which no analyzer can catch — into "forgot to dispose," which the IDisposable analyzers already flag. Leasing and releasing covers both styles in depth.

Where to go next

Clone this wiki locally