csharp-async
Scannednpx machina-cli add skill github/awesome-copilot/csharp-async --openclawC# Async Programming Best Practices
Your goal is to help me follow best practices for asynchronous programming in C#.
Naming Conventions
- Use the 'Async' suffix for all async methods
- Match method names with their synchronous counterparts when applicable (e.g.,
GetDataAsync()forGetData())
Return Types
- Return
Task<T>when the method returns a value - Return
Taskwhen the method doesn't return a value - Consider
ValueTask<T>for high-performance scenarios to reduce allocations - Avoid returning
voidfor async methods except for event handlers
Exception Handling
- Use try/catch blocks around await expressions
- Avoid swallowing exceptions in async methods
- Use
ConfigureAwait(false)when appropriate to prevent deadlocks in library code - Propagate exceptions with
Task.FromException()instead of throwing in async Task returning methods
Performance
- Use
Task.WhenAll()for parallel execution of multiple tasks - Use
Task.WhenAny()for implementing timeouts or taking the first completed task - Avoid unnecessary async/await when simply passing through task results
- Consider cancellation tokens for long-running operations
Common Pitfalls
- Never use
.Wait(),.Result, or.GetAwaiter().GetResult()in async code - Avoid mixing blocking and async code
- Don't create async void methods (except for event handlers)
- Always await Task-returning methods
Implementation Patterns
- Implement the async command pattern for long-running operations
- Use async streams (IAsyncEnumerable<T>) for processing sequences asynchronously
- Consider the task-based asynchronous pattern (TAP) for public APIs
When reviewing my C# code, identify these issues and suggest improvements that follow these best practices.
Source
git clone https://github.com/github/awesome-copilot/blob/main/plugins/csharp-dotnet-development/skills/csharp-async/SKILL.mdView on GitHub Overview
Learn practical guidelines for writing safe, efficient asynchronous code in C#. This covers naming conventions, return types, exception handling, performance patterns, and common pitfalls to avoid.
How This Skill Works
The guidelines prescribe naming async methods with an Async suffix and aligning them with synchronous versions when possible. They also outline return types (Task, Task<T>, or ValueTask<T>), error handling strategies, and key performance patterns such as WhenAll and WhenAny. Finally, they emphasize avoiding blocking calls and using cancellation tokens for long running work.
When to Use It
- Designing library or API methods that perform IO-bound work asynchronously
- Coordinating multiple asynchronous operations in parallel to improve throughput
- Implementing timeouts or first-completed patterns with Task.WhenAny
- Optimizing in hot paths with ValueTask for reduced allocations
- Long-running operations that should support cancellation tokens
Quick Start
- Step 1: Rename all async methods to end with Async and align with sync counterparts
- Step 2: Return Task or Task<T> (or ValueTask<T> for hot paths); avoid async void; add ConfigureAwait(false) in library code
- Step 3: Implement parallelism and cancellation with Task.WhenAll, Task.WhenAny, and CancellationToken; test for blocking calls
Best Practices
- Name async methods with Async suffix and align names with their synchronous counterparts when feasible
- Return Task<T> for value-returning methods and Task for void-like operations; consider ValueTask<T> for hot paths
- Avoid async void except for event handlers; propagate errors with Task.FromException when returning Task
- Wrap awaits in try/catch, and use ConfigureAwait(false) in library code to prevent deadlocks
- Use Task.WhenAll for parallelism and Task.WhenAny for timeouts or first-completed tasks; prefer cancellation tokens
- Avoid blocking calls like Wait, Result, or GetAwaiter().GetResult and avoid mixing sync with async
- Adopt async command patterns, use IAsyncEnumerable<T> for asynchronous streams, and follow TAP for public APIs
Example Use Cases
- GetDataAsync returning Task<Data> demonstrates naming and return type
- LoadFilesAsync uses Task.WhenAll to read multiple files in parallel
- Timeout pattern implemented with Task.WhenAny to cancel a long operation
- An API that exposes ValueTask<T> for a hot-path method
- Long-running operation that accepts a CancellationToken and handles cancellation