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

如何避免异步请求场景下的执行超时错误?

优化异步任务执行时间与超时问题解决方案

针对你提供的异步并行任务代码,以下是具体的优化方向和修改建议,解决超时问题并提升执行效率:

1. 重构ContinueWith为await链式调用

原代码使用ContinueWith构建任务依赖链,不仅可读性差,还可能引入不必要的线程调度开销。改用await可以简化逻辑,减少调度成本:

// 原代码
var buildOsmTask = director.BuildOsmAsync(buildingStory?.Id);
var modelTask = buildOsmTask.ContinueWith(task => builder.GetOsm(), TaskScheduler.Default);
var idfTextTask = modelTask.ContinueWith(task => ProjectUtils.GenerateIDFTextAsync(task.Result), TaskScheduler.Default).Unwrap();

// 优化后
await director.BuildOsmAsync(buildingStory?.Id).ConfigureAwait(false);
var osmModel = builder.GetOsm();
var idfTextTask = ProjectUtils.GenerateIDFTextAsync(osmModel);

2. 修复数据库操作的逻辑错误

原代码提前调用dbContext.SaveChangesAsync(),但此时simulation对象尚未添加到上下文,导致该保存操作无效,还可能占用数据库连接资源。调整顺序,确保添加实体后再执行保存:

if (response.IsSuccessful)
{
    simulation.StatusId = LoadSimulationStatus.SCHEDULED.Id;
    simulation.JobId = response.Content;
    simulation.LastUpdatedAtUTC = DateTime.UtcNow;
    dbContext.LoadSimulationRuns.Add(simulation);

    // 移到此处,确保保存新添加的simulation
    await dbContext.SaveChangesAsync().ConfigureAwait(false);
    await dbContext.Entry(simulation).LoadNavigations().ConfigureAwait(false);
    
    // 事件发送移到此处,确保发送完整的simulation数据
    await SendSimulationUpdatedEvent(eventSender, simulation).ConfigureAwait(false);

    ok = true;
    insertedIds.Add($"{simulation.Id}.{simulation.JobId}");
}

3. 复用RestClient实例

每次创建RestClient会带来初始化开销,复用实例可以减少这部分耗时,同时统一配置超时:

// 在类中定义静态复用的RestClient
private static readonly RestClient _simulationClient;

static YourClassName(IConfiguration configuration)
{
    _simulationClient = new RestClient(configuration["Endpoints:SimulationServer"]);
    // 根据实际需求设置超时时间,比如30秒
    _simulationClient.Timeout = TimeSpan.FromSeconds(30);
}

// 修改SendPostRequestAsync方法
private static async Task<RestResponse> SendPostRequestAsync(string projectNumber, Guid simulationId, Task<string> idfTextTask)
{
    var idfText = await idfTextTask.ConfigureAwait(false);
    var request = new RestRequest($"api/simulation/{projectNumber}/{simulationId}", Method.Post);
    request.AddHeader("Content-Type", "text/plain");
    request.AddParameter("text/plain", idfText, ParameterType.RequestBody);
    var response = await _simulationClient.ExecuteAsync(request).ConfigureAwait(false);

    return response;
}

4. 优化CPU密集型任务的执行

如果GenerateIDFTextAsync是CPU密集型操作,将其放入线程池执行,避免阻塞异步调用链:

// 用Task.Run将CPU密集型任务移到线程池
var idfTextTask = Task.Run(() => ProjectUtils.GenerateIDFTextAsync(osmModel)).Unwrap();

5. 增加请求重试机制

针对外部API调用的超时或临时失败,使用重试策略提升成功率:

// 示例:实现3次重试,间隔1秒
var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .Or<TaskCanceledException>() // 超时会抛出此异常
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(1));

var response = await retryPolicy.ExecuteAsync(async () =>
    await _simulationClient.ExecuteAsync(request).ConfigureAwait(false));

6. 移除不必要的数据库操作

检查dbContext.Entry(simulation).LoadNavigations()是否必要,如果不需要立即访问导航属性,可移除该操作以减少数据库查询耗时。

7. 调整任务并行策略

原代码中buildOsmTask→idfTextTask→responseTask是串行依赖,无法并行,但可确保其他独立任务(如数据库保存、事件发送)仅在必要时执行,避免无效的并行等待。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:24:56