0.1.0 · released · .NET 10Read Markdown ↗

Copy a C# stream to multiple destinations

TeeForge 0.1.0 · .NET 10 · released

Select the extension with a destination collection; caller streams remain open and unflushed.

Run from the repository root:

dotnet run --project samples/TeeForge.Quickstart -c Release -- copy

The runner calls this example's RunAsync method with a cancellation token. The example checks its result and throws on failure. Source: samples/TeeForge.Quickstart/CopyExample.cs.

using TeeForge.Broadcasting;

namespace TeeForge.Quickstart;

internal static class CopyExample
{
    public static async Task RunAsync(CancellationToken cancellationToken)
    {
        byte[] payload = "Copy a C# stream to multiple destinations."u8.ToArray();
        await using var source = new MemoryStream(payload);
        await using var first = new MemoryStream();
        await using var second = new MemoryStream();

        // The collection selects TeeForge's extension rather than Stream's single-destination method.
        Stream[] destinations = [first, second];
        await source.CopyToAsync(destinations, cancellationToken);

        // CopyToAsync leaves caller streams open and does not flush them.
        await first.FlushAsync(cancellationToken);
        await second.FlushAsync(cancellationToken);
        if (!first.ToArray().AsSpan().SequenceEqual(payload) ||
            !second.ToArray().AsSpan().SequenceEqual(payload) || !source.CanRead)
        {
            throw new InvalidOperationException("Both destinations must receive the full payload, and the source must stay open.");
        }
    }
}

Usage guide · All recipes