受 Node.js async 启发的 C# 异步流程控制库。提供可组合的原语,以清晰、可读的方式编排回调和 Task-based 异步工作流。
嵌套异步回调很快就会变得难以阅读——尤其是在游戏开发中,复杂的加载、动画、网络和逻辑序列是常态。CsAsync 将深层嵌套的"回调地狱"转变为扁平、线性、可维护的代码。
| 原语 | 游戏用例 |
|---|---|
Waterfall |
游戏初始化 — 加载配置 → 预加载资源 → 初始化子系统 → 显示主菜单,每一步等待上一步完成。过场动画序列 — 播放对话 → 等待输入 → 触发动画 → 推进剧情,配合内置超时可跳过。 |
Waterfall + 重试 |
匹配/登录 — 连接服务器失败时自动重试 N 次再放弃。 |
Whilst |
回合制游戏循环 — 游戏未结束时持续处理回合。AI 巡逻 — 敌人存活时循环执行巡逻路线。 |
DoWhilst |
登录流程 — 至少尝试登录一次,凭证失败则重试。加载重试 — 尝试加载资源,失败重试直到成功或达到上限。 |
Each<T> |
批量资源加载 — 遍历资源列表,逐个加载贴图/模型并报告进度。实体初始化 — 逐个生成 NPC 列表以避免帧率波动。 |
Parallel |
并发资源预加载 — 并行加载贴图、音频、配置,通过并发上限控制内存/IO。多人准备检查 — 同时等待所有玩家发出就绪信号。 |
- API 编排 — 串联多个依赖前序结果的后端接口调用。
- 文件处理 — 顺序或并行批量处理目录中的文件。
- UI 工作流 — 分步向导、多页表单提交。
- 数据管道 — ETL 操作,支持每阶段超时和错误恢复。
dotnet add package CsAsync| 类 | 描述 |
|---|---|
Waterfall |
顺序执行任务,每个任务调用 callback 进入下一个 |
Whilst |
条件为真时循环执行异步任务,每次迭代前重新评估条件 |
DoWhilst |
类似 Whilst,但至少执行一次后再测试条件 |
Each<T> |
遍历集合,对每个元素顺序执行异步操作 |
Parallel |
并发执行多个异步任务,支持并发数限制 |
所有类均支持 回调式 API(Start)和 Task-based API(RunAsync),以及 CancellationToken 取消。
顺序执行任务。每个任务必须调用回调才会进入下一个任务。任一任务出错则立即终止。
var waterfall = new Waterfall();
waterfall.AddTask(cb =>
{
DoRequest1(() => cb(null));
});
waterfall.AddTask(cb =>
{
DoRequest2(() => cb(null));
});
await waterfall.RunAsync();var options = new WaterfallOptions
{
TimeoutPerTask = TimeSpan.FromSeconds(30), // 单任务超时
MaxRetriesPerTask = 2 // 单任务最大重试次数
};
var waterfall = new Waterfall(options);
waterfall.AddTask(cb =>
{
DoRequest(() => cb(null));
});
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1));
await waterfall.RunAsync(cts.Token);var waterfall = new Waterfall();
waterfall.AddTask(cb => { /* 任务 1 */ cb(null); });
waterfall.AddTask(cb => { /* 任务 2 */ cb(null); });
waterfall.Start(ex =>
{
if (ex != null)
Console.WriteLine($"失败: {ex.Message}");
else
Console.WriteLine("全部完成!");
});当条件为真时循环执行,每次迭代前重新评估条件。
int count = 0;
var whilst = new Whilst(
test: () => count < 5,
fn: cb =>
{
Console.WriteLine($"第 {count} 次迭代");
count++;
cb(null);
});
await whilst.RunAsync();类似 Whilst,但至少执行一次后再评估条件。
int count = 0;
var doWhilst = new DoWhilst(
test: () => count < 3,
fn: cb =>
{
Console.WriteLine($"计数: {count}");
count++;
cb(null);
});
await doWhilst.RunAsync();顺序遍历集合,遇到第一个错误时终止。
var items = new[] { "a", "b", "c" };
var each = new Each<string>(items, (item, cb) =>
{
Console.WriteLine($"处理: {item}");
cb(null);
});
await each.RunAsync();带取消支持:
using var cts = new CancellationTokenSource();
var each = new Each<int>(Enumerable.Range(1, 100), (item, cb) =>
{
if (item > 10) cts.Cancel();
cb(null);
});
await each.RunAsync(cts.Token); // 抛出 OperationCanceledException并发执行多个任务,任一失败即终止。
var parallel = new Parallel();
parallel.AddTask(cb => { DoRequest1(() => cb(null)); });
parallel.AddTask(cb => { DoRequest2(() => cb(null)); });
parallel.AddTask(cb => { DoRequest3(() => cb(null)); });
await parallel.RunAsync();并发数限制:
var options = new ParallelOptions { MaxConcurrency = 3 };
var parallel = new Parallel(options);
for (int i = 0; i < 100; i++)
{
parallel.AddTask(cb => { ProcessItem(i, () => cb(null)); });
}
await parallel.RunAsync(); // 最多 3 个任务同时执行Whilst构造函数不再接收回调 — 改用Start(callback)或RunAsync()。Each<T>现在是泛型类。非泛型Each标记为[Obsolete]以保持向后兼容。Waterfall.AddTask直接接收Action<Action<Exception>>。TaskCallback重载已弃用。- 所有类通过
Start(callback, ct)和RunAsync(ct)支持CancellationToken。 - 新增
DoWhilst和Parallel。
受 Node.js async 库启发。
技术交流 QQ 群:242500383
MIT