plugins/languages/csharp/skills/async/SKILL.md
C# 异步并发编程规范。涵盖 async/await、ConfigureAwait、CancellationToken 传播、 IAsyncEnumerable 异步流、System.Threading.Channels 生产者-消费者、 Parallel.ForEachAsync 并行处理、ValueTask 优化、TaskCompletionSource、 死锁与线程池饥饿排查。当编写或审查异步代码、排查 deadlock、调优并发吞吐, 或说 "async"、"await"、"Task"、"CancellationToken"、"死锁"、"thread pool starvation"、 "异步流"、"Channels"、"ValueTask" 时加载。
npx skillsauth add lazygophers/ccplugin csharp-asyncInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
异步代码默认按 ASP.NET Core / library 场景; UI 场景在末尾单列。
| 禁止 | 替代 |
|------|------|
| task.Result / task.Wait() | await task |
| Task.Run(() => syncIO) 来"异步化" | 使用真正的异步 API |
| async void 非事件处理器 | async Task |
| 漏传 CancellationToken | 全链路传递, 尊重 ct.ThrowIfCancellationRequested() |
| Thread.Sleep 在异步方法中 | await Task.Delay(ts, ct) |
| 同步上下文同步等异步 (库代码) | 全程异步 |
| _ = FireAndForgetAsync() 直接丢弃 | 包装 try/catch + 日志 |
public async Task<User> GetUserAsync(int id, CancellationToken ct = default)
{
return await _db.Users.FirstAsync(u => u.Id == id, ct);
}
Async 后缀命名CancellationToken 永远是最后一个参数, 提供 defaultTask / ValueTask; 不要返回 voidValueTask; 其余用 Taskawait x.ConfigureAwait(false), 避免捕获 SynchronizationContextfalsect 必须穿透所有异步调用。组合多源取消:
using var cts = CancellationTokenSource.CreateLinkedTokenSource(
userCt, _appLifetime.ApplicationStopping);
cts.CancelAfter(TimeSpan.FromSeconds(30));
await DoWorkAsync(cts.Token);
var userTask = _userRepo.FindAsync(id, ct);
var ordersTask = _orderRepo.GetByUserAsync(id, ct);
await Task.WhenAll(userTask, ordersTask);
return (await userTask, await ordersTask);
数据源是流式时优先使用, 按需消费、自动取消:
public async IAsyncEnumerable<Order> StreamOrdersAsync(
[EnumeratorCancellation] CancellationToken ct = default)
{
await foreach (var o in _db.Orders.AsAsyncEnumerable().WithCancellation(ct))
yield return o;
}
调用方: await foreach (var o in svc.StreamOrdersAsync(ct)) { ... }。
var ch = Channel.CreateBounded<Job>(new BoundedChannelOptions(100)
{
FullMode = BoundedChannelFullMode.Wait,
SingleReader = false,
});
// Producer: await ch.Writer.WriteAsync(job, ct); 完成: ch.Writer.Complete();
// Consumer: await foreach (var j in ch.Reader.ReadAllAsync(ct)) ...
Bounded 提供背压; Unbounded 仅用于已知有界场景。
CPU/IO 混合 → Parallel.ForEachAsync 控制并发:
await Parallel.ForEachAsync(items,
new ParallelOptions { MaxDegreeOfParallelism = 8, CancellationToken = ct },
async (item, token) => await ProcessAsync(item, token));
纯 IO 限流 → Task.WhenAll + SemaphoreSlim:
using var gate = new SemaphoreSlim(10);
var tasks = urls.Select(async url =>
{
await gate.WaitAsync(ct);
try { return await _http.GetAsync(url, ct); }
finally { gate.Release(); }
});
var results = await Task.WhenAll(tasks);
ValueTaskValueTask 不能 await 多次、不能并发 awaitTaskpublic ValueTask<User?> GetUserAsync(int id, CancellationToken ct = default)
=> _cache.TryGetValue(id, out var u) ? new(u) : new(LoadAsync(id, ct));
排查思路:
dotnet-counters monitor --counters System.Runtime 看 ThreadPool Queue Lengthdotnet-stack report 找 sync-over-async 调用GetAwaiter().GetResult() / .Result? 删除ConfigureAwait(false)_ = Task.Run(async () =>
{
try { await DoBackgroundAsync(ct); }
catch (OperationCanceledException) { }
catch (Exception ex) { _logger.LogError(ex, "background failed"); }
}, ct);
async Task 测试FakeTimeProvider 测试基于时间的异步逻辑, 避免真实 Task.DelayTask.WaitAsync(timeout) 兜底async void, 内部必须 try/catchDispatcher / MainThread.BeginInvokeOnMainThreadtools
UI/UX 与布局设计——做界面布局/结构/导航/组件/交互的设计决策。触发:做UI/UX/布局/排版/导航/组件/交互/栅格/响应式/图表选型/字体配对。按媒介路由 HTML/Web、原生 App(iOS/Android/桌面)、CLI、TUI。需后端动态系统不适用;配色/主题/色板走姊妹 skill design-color。
tools
主题与配色设计——做颜色搭配/调色板/主题/品牌色阶/暗模式的设计决策。触发:选配色/调色/主题/色板/品牌色/暗模式/对比度/色盲/UI风格。按媒介路由 HTML/Web(CSS变量)、原生App(平台token)、CLI(ANSI)、TUI(真彩/256/16降级)。保证可访问性(对比度/色盲安全)。需后端动态系统不适用;UI/UX 布局/组件/交互走姊妹 skill design-uiux。
tools
跨任意组件(plugin/skill/agent/command)的验证驱动优化循环纪律 skill。当用户要优化某个已有组件却无明确方向、或要防止改了反而更差(自评乐观偏差 / 多维同改归因失效 / 为凑分加废话膨胀)、或要把一套通用「评分→单变量改→改后验证严格更好才留否则回滚→触顶停」的纪律套到任意组件上时使用。管优化过程本身的纪律(validation gate / ratchet / 独立验证 / 触顶停),不评单组件深度(交 skill-dev),不查插件接线(交 plugin-dev)。仅手动 /optimize-any 触发。
data-ai
两层规则记忆 (基于 .skein/spec)。planning 时 recall 召回相关规则、task finish 后 sediment 沉淀学习 + prune 自动精简过期/重复/断链规则。core 常驻硬规 + recall 按需召回, 经判定门自动写盘 (不逐次问用户)。产出 .skein/spec 下 core/recall 规则文件 + index。另支持空仓 bootstrap 播种规则基线、记忆大面积失效 (大重构/换栈) 时 reconstruct 可逆归档后按项目类型分型重建、maintain 手动体检 (超预算/stale/断链/重复/废弃, --apply 自动修复)、auto-fix (Stop hook 写 .pending-fix 标记 → main 派 skein-specer bg 跑 maintain --apply 全自动修, 断链只报告)。