using System.Threading.Channels; public sealed record WorkRequest(int Value); public sealed record WorkReceipt(int Value,int ScopeId); public sealed record WorkMessage(int Value,CancellationToken Token) { public TaskCompletionSource Completion { get; }=new(TaskCreationOptions.RunContinuationsAsynchronously); } public sealed class WorkQueue { public Channel Items { get; }=Channel.CreateBounded(4); } public sealed class ScopeEvidence { private int created,disposed,live; public int Created=>Volatile.Read(ref created); public int Disposed=>Volatile.Read(ref disposed); public int Live=>Volatile.Read(ref live); public int Start() { Interlocked.Increment(ref live); return Interlocked.Increment(ref created); } public void End() { Interlocked.Decrement(ref live); Interlocked.Increment(ref disposed); } } public sealed class ScopedOperation : IAsyncDisposable { private readonly ScopeEvidence evidence; private int disposed; public int Id { get; } public ScopedOperation(ScopeEvidence evidence) { this.evidence=evidence; Id=evidence.Start(); } public async Task ProcessAsync(int value,CancellationToken token) { await Task.Delay(2,token); return new(value*2,Id); } public ValueTask DisposeAsync() { if(Interlocked.Exchange(ref disposed,1)==0)evidence.End(); return ValueTask.CompletedTask; } } public sealed class ScopedWorker(WorkQueue queue,IServiceScopeFactory scopes) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await foreach(var item in queue.Items.Reader.ReadAllAsync(stoppingToken)) { using var owner=CancellationTokenSource.CreateLinkedTokenSource(stoppingToken,item.Token); try { WorkReceipt result; await using(var scope=scopes.CreateAsyncScope()) result=await scope.ServiceProvider.GetRequiredService().ProcessAsync(item.Value,owner.Token); item.Completion.TrySetResult(result); } catch(OperationCanceledException) { item.Completion.TrySetCanceled(owner.Token); } } } public override async Task StopAsync(CancellationToken token) { queue.Items.Writer.TryComplete(); try { if(ExecuteTask is not null) await ExecuteTask.WaitAsync(token); } finally { await base.StopAsync(token); } } } public static class WorkerLabs { public static void Map(WebApplication app) { app.MapPost("/worker",async(WorkRequest input,WorkQueue queue,CancellationToken token)=> { if(input.Value is <1 or >10)return Results.BadRequest(); var item=new WorkMessage(input.Value,token); if(!queue.Items.Writer.TryWrite(item))return Results.StatusCode(429); return Results.Ok(await item.Completion.Task.WaitAsync(token)); }); app.MapGet("/worker/evidence",(ScopeEvidence evidence)=>new { evidence.Created,evidence.Disposed,evidence.Live }); } }