如何在谓词条件满足时立即取消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
相关产品推荐
相关产品推荐

