You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在谓词条件满足时立即取消CancellationToken?

异步任务取消的轮询谓词实现方案探讨

现有异步方法与当前取消逻辑

我有如下组合异步方法:

CancellationTokenSource cts;
protected virtual async void Test() {
    cts = new CancellationTokenSource();
    await Attack(cts.Token);
}

protected virtual async Task Attack(CancellationToken token) {
    token.ThrowIfCancellationRequested();
    await MoveToTarget(token);
    await DoAttackAnimation(token);
    await ReturnToBase(token);
}

为了在特定条件满足时取消攻击,我当前的实现方式是:

protected virtual void EnsureConditions() {
    if (HP <= 0 || IsParalyzed || TargetIsDead) {
        cts?.Cancel();
        cts?.Dispose();
        cts = null;
    }
}

修改后的Attack方法需要在每个await前后插入检查:

protected virtual async Task Attack(CancellationToken token) {
    EnsureConditions();
    await MoveToTarget(token);
    EnsureConditions();
    await DoAttackAnimation(token);
    EnsureConditions();
    await ReturnToBase(token);
}

这种方式存在明显问题:

  • 不仅要在await之间插入检查方法,还要在MoveToTarget、DoAttackAnimation、ReturnToBase的内部也插入,因为条件可能在这些方法执行过程中变化。
  • 长期维护会产生大量重复代码。

事件驱动的标准取消方案

我知道CancellationTokenSource的预期用法是事件触发时取消,而非主动轮询条件,比如通过监听状态变化事件来处理:

public void OnHPChanged() {
    if (HP <= 0) {
        // 取消并释放CTS
        cts?.Cancel();
        cts?.Dispose();
        cts = null;
    }
}

public void OnParalyzed() {
    // 取消并释放CTS
    cts?.Cancel();
    cts?.Dispose();
    cts = null;
}

public void OnTargetDied() {
    // 取消并释放CTS
    cts?.Cancel();
    cts?.Dispose();
    cts = null;
}

这种方式不需要到处插入检查代码,是更规范的方案。但我还是想了解,有没有更优雅的轮询谓词实现方式?我的理想场景是能给CancellationTokenSource附加一个谓词,当谓词返回真时自动取消,示例如下:

protected virtual async void Test() {
    cts = new CancellationTokenSource();
    cts.AttachPredicate(EnsureConditions); // 当谓词条件满足时自动取消CTS
    await Attack(cts.Token);
}

我考虑过通过控制任务执行顺序来实现,但感觉不够稳妥,想请教更可靠的实现方式。

内容的提问来源于stack exchange,提问作者Saturn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:30:08