Skip to content

Latest commit

 

History

History
228 lines (162 loc) · 5.82 KB

File metadata and controls

228 lines (162 loc) · 5.82 KB

CsAsync

English

受 Node.js async 启发的 C# 异步流程控制库。提供可组合的原语,以清晰、可读的方式编排回调和 Task-based 异步工作流。

为什么选择 CsAsync?

嵌套异步回调很快就会变得难以阅读——尤其是在游戏开发中,复杂的加载、动画、网络和逻辑序列是常态。CsAsync 将深层嵌套的"回调地狱"转变为扁平、线性、可维护的代码。

游戏开发场景

原语 游戏用例
Waterfall 游戏初始化 — 加载配置 → 预加载资源 → 初始化子系统 → 显示主菜单,每一步等待上一步完成。过场动画序列 — 播放对话 → 等待输入 → 触发动画 → 推进剧情,配合内置超时可跳过。
Waterfall + 重试 匹配/登录 — 连接服务器失败时自动重试 N 次再放弃。
Whilst 回合制游戏循环 — 游戏未结束时持续处理回合。AI 巡逻 — 敌人存活时循环执行巡逻路线。
DoWhilst 登录流程 — 至少尝试登录一次,凭证失败则重试。加载重试 — 尝试加载资源,失败重试直到成功或达到上限。
Each<T> 批量资源加载 — 遍历资源列表,逐个加载贴图/模型并报告进度。实体初始化 — 逐个生成 NPC 列表以避免帧率波动。
Parallel 并发资源预加载 — 并行加载贴图、音频、配置,通过并发上限控制内存/IO。多人准备检查 — 同时等待所有玩家发出就绪信号。

通用场景

  • API 编排 — 串联多个依赖前序结果的后端接口调用。
  • 文件处理 — 顺序或并行批量处理目录中的文件。
  • UI 工作流 — 分步向导、多页表单提交。
  • 数据管道 — ETL 操作,支持每阶段超时和错误恢复。

安装

dotnet add package CsAsync

API 概览

类 描述
Waterfall 顺序执行任务,每个任务调用 callback 进入下一个
Whilst 条件为真时循环执行异步任务,每次迭代前重新评估条件
DoWhilst 类似 Whilst,但至少执行一次后再测试条件
Each<T> 遍历集合,对每个元素顺序执行异步操作
Parallel 并发执行多个异步任务,支持并发数限制

所有类均支持 回调式 API(Start)和 Task-based API(RunAsync),以及 CancellationToken 取消。


Waterfall

顺序执行任务。每个任务必须调用回调才会进入下一个任务。任一任务出错则立即终止。

Task-based API(推荐)

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);

回调式 API

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("全部完成!");
});

Whilst

当条件为真时循环执行,每次迭代前重新评估条件。

int count = 0;
var whilst = new Whilst(
    test: () => count < 5,
    fn: cb =>
    {
        Console.WriteLine($"第 {count} 次迭代");
        count++;
        cb(null);
    });

await whilst.RunAsync();

DoWhilst

类似 Whilst,但至少执行一次后再评估条件。

int count = 0;
var doWhilst = new DoWhilst(
    test: () => count < 3,
    fn: cb =>
    {
        Console.WriteLine($"计数: {count}");
        count++;
        cb(null);
    });

await doWhilst.RunAsync();

Each<T>

顺序遍历集合,遇到第一个错误时终止。

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

Parallel

并发执行多个任务,任一失败即终止。

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 个任务同时执行

从 v1.x 迁移

  • 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

License

MIT