Dotnet async
Write async C# that never blocks on tasks, flows cancellation everywhere, and uses ValueTask where it pays. Use when writing .NET async code or debugging thread-pool starvation and deadlocks.From its SKILL.md
npx -y skills add Amey-Thakur/AI-SKILLS --skill dotnet-asyncAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 25 days oldThe repository was created 25 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.7 KB, 831 tokens by cl100k_base, as published. Nobody here has run it
.NET async
Async in .NET is viral by design: one blocking call inside an async stack undoes the whole model. The rules are few and absolute: async all the way, cancellation everywhere, and never sync-over-async.
Method
- Go async end to end. Controllers, services, repositories:
async Taskfrom the entry point down to the I/O. The forbidden moves are.Result,.Wait(), and.GetAwaiter().GetResult()on incomplete tasks: they block a thread-pool thread waiting for work that needs a thread-pool thread, which is how services deadlock under load and starve at scale. If a sync boundary is truly unavoidable, isolate it at the outermost edge and document it. - Flow CancellationToken through every signature. Accept a
token, pass it to every awaited call, and honor it in loops;
ASP.NET hands you
RequestAbortedso abandoned requests stop costing work (the timeouts-and-retries budget idea, in-process). Link tokens (CreateLinkedTokenSource) for per-operation timeouts layered on caller cancellation; treatOperationCanceledExceptionas control flow, not an error to log as failure (see kotlin-idioms' identical rule). - Return the right task shape.
Taskfor most APIs;ValueTaskonly on hot paths that usually complete synchronously (cache hits) and with its rules respected: await once, never store or await twice.async voidis for event handlers alone; anywhere else it swallows exceptions and breaks composition. Avoid fake async (Task.Runwrapping sync work in a request path): it burns two threads to pretend one blocking call is async. - Compose with the combinators, bounded.
Task.WhenAllfor independent fan-out (exceptions aggregate: catch and inspect all);Task.WhenAnyfor races and timeouts;Parallel.ForEachAsyncor aSemaphoreSlimgate for bounded concurrency against downstreams (see backpressure);IAsyncEnumerablewithawait foreachfor streams, passing the token viaWithCancellation. Fire-and-forget work goes to a hosted background service with error handling, not a dropped task (see background-jobs). - Know where ConfigureAwait matters. Library code:
ConfigureAwait(false)throughout (no context to preserve, avoids deadlocks with context-bound callers). ASP.NET Core has no synchronization context, so app code there gains nothing; UI frameworks (WPF/MAUI) do have one, and returning to it after awaits is the point. The rule is per project type, set once, enforced by analyzer. - Let the analyzers and metrics enforce it. Enable the async analyzers (CA2007, CA2012, VSTHRD-class rules) in CI so blocking calls and misused ValueTasks fail the build (see linting-setup); watch thread-pool queue length and starvation counters in production dashboards (see infrastructure-monitoring): rising queue length with idle CPU is sync-over-async somewhere.
Boundaries
- Async buys scalability for I/O-bound work, not speed for
CPU-bound work; heavy compute belongs on dedicated workers or
Task.Runat the boundary with concurrency limits (the python-concurrency triage, .NET edition). - Async does not synchronize shared state; two awaits touching the same dictionary still race (see jvm-memory-model's lesson, mutatis mutandis: use concurrent collections or locks).
- Legacy interfaces that are sync-only (old ADO drivers, COM) cannot be made truly async by wrapping; plan the dependency upgrade rather than laundering blocking calls.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.