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

异步任务:是否存在支持短路的TrueForAll()方法或实现模式?

异步条件检查的快速失败并行执行方案

问题背景

现有一批返回布尔值的异步条件检查任务,当前为串行执行逻辑,任一条件不满足则返回null。核心需求如下:

  • 无需串行执行,任一任务返回"不通过"时立即终止其余任务并返回null
  • 任务执行速度不确定(部分涉及IO操作),不想固定检查顺序
  • 逻辑需在循环中执行约3500万次,提前返回对性能至关重要
  • 该检查逻辑需在数百个类中复用,避免频繁调整顺序

当前实现代码:

public override async Task<TradeEntry?> TryGetNewTradeEntryAsync(RequestNewTradeEntry request)
{
    if (await condition.FalseAsync<IsPeriodEnd>
        (new(request, this.Settings.PeriodGap, this.productCode)))
    {
        return null;
    }

    if (await condition.FalseAsync<EventActiveWithAvailableEntries>
        (new(request, this.productCode, this)))
    {
        return null;
    }

    if (await condition.FalseAsync<IsAfterNewsEvent>
        (new(request, 1, this.Period1m, this.productCode)))
    {
        return null;
    }

    if (await condition.TrueAsync<AfterNewsClosedOverExtremeSwingPointBeforeNews>
        (new(request, this.Settings.SwingPointLookback, request.Bias.Opposite(), this.Period1m, this.productCode)))
    {
        // find a gap...
    }
    else if (await condition.TrueAsync<HasNoUnclosedOverSwingPointBeforeNews>
        (new(request, this.Settings.SwingPointLookback, request.Bias.Opposite(), this.Period1m, this.productCode)))
    {
        // look for new swing points closed over...
    }
}

解决方案

可以通过CancellationTokenSource结合Task.WhenAny实现快速失败的并行检查模式,无需固定任务顺序,任一条件不满足时立即取消其余任务。

核心思路

  1. 为所有检查任务绑定同一个取消令牌,任一任务失败时触发取消信号
  2. 用Task.WhenAny监听任务完成状态,先完成的任务优先判断
  3. 失败时立即取消剩余任务,避免无效执行;所有任务完成后再处理后续逻辑

重构后的代码示例

public override async Task<TradeEntry?> TryGetNewTradeEntryAsync(RequestNewTradeEntry request)
{
    using var cts = new CancellationTokenSource();
    var token = cts.Token;

    // 定义所有前置检查任务:原逻辑中FalseAsync等价于检查任务返回false时失败
    var mandatoryChecks = new List<Task<bool>>
    {
        // 转换为TrueAsync,因为我们需要判断"条件是否通过",返回false则触发失败
        condition.TrueAsync<IsPeriodEnd>(new(request, Settings.PeriodGap, productCode), token),
        condition.TrueAsync<EventActiveWithAvailableEntries>(new(request, productCode, this), token),
        condition.TrueAsync<IsAfterNewsEvent>(new(request, 1, Period1m, productCode), token)
    };

    // 并行监听任务完成,快速失败
    while (mandatoryChecks.Count > 0)
    {
        var completedTask = await Task.WhenAny(mandatoryChecks);
        mandatoryChecks.Remove(completedTask);

        // 若任务返回false,立即取消所有剩余任务并返回null
        if (!await completedTask)
        {
            cts.Cancel();
            // 等待剩余任务完成/取消,避免资源泄漏
            await Task.WhenAll(mandatoryChecks);
            return null;
        }
    }

    // 前置检查通过,处理分支逻辑
    var swingCheck1 = condition.TrueAsync<AfterNewsClosedOverExtremeSwingPointBeforeNews>(
        new(request, Settings.SwingPointLookback, request.Bias.Opposite(), Period1m, productCode), token);
    
    var swingCheck2 = condition.TrueAsync<HasNoUnclosedOverSwingPointBeforeNews>(
        new(request, Settings.SwingPointLookback, request.Bias.Opposite(), Period1m, productCode), token);

    var completedSwingTask = await Task.WhenAny(swingCheck1, swingCheck2);
    cts.Cancel();
    await Task.WhenAll(swingCheck1, swingCheck2);

    if (completedSwingTask == swingCheck1 && await swingCheck1)
    {
        // find a gap...
    }
    else if (completedSwingTask == swingCheck2 && await swingCheck2)
    {
        // look for new swing points closed over...
    }

    // 根据实际逻辑返回TradeEntry或null
    return null;
}

关键注意事项

  • 所有条件检查方法需支持接收CancellationToken,并在IO操作(数据库查询、文件读取)中主动检查令牌,确保能及时终止任务
  • 若循环执行次数极高(3500万次),可考虑复用CancellationTokenSource对象池,减少对象创建开销
  • 该模式可封装为通用工具方法,在数百个类中复用,避免重复编写逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:34:57