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

基于查询参数并行调用API任务的异常问题及实现方案问询

问题分析与解决方案

原代码抛出ArgumentException的原因

Task.WhenAll的参数不允许包含null任务,你原代码中当users或version参数未被请求时,会给getUsers或VersionTask赋值为null,传入Task.WhenAll后就触发了这个异常。

优化后代码的潜在问题

你后来用列表存储任务的方式避免了null,但依赖列表索引(appTasks[1]、appTasks[2])获取结果的逻辑有漏洞:

  • 若只请求了用户数据,列表里只有2个任务,取appTasks[2]会触发索引越界异常
  • 若只请求了版本数据,列表里也是2个任务,取appTasks[1]会拿到版本任务的结果,导致类型转换错误

正确实现方式

单独保存每个可选任务的引用,只将需要执行的任务加入集合,既避免null,又能安全获取结果:

// 1. 启动主任务
Task<AppData> appDataTask = myClient.GetAppDataAsync(identifierId, identifierName, version, token);

// 2. 初始化可选任务,仅当需要时创建实例
Task<Users> usersTask = null;
if (users.HasValue && users.Value)
{
    usersTask = FetchUsers(titleId: appId, token: token);
}

Task<VersionedApp> versionTask = null;
if (version.HasValue && version.Value)
{
    versionTask = FetchVersionApp(titleId: TitleId, token: token);
}

// 3. 收集所有非null的任务,避免传入null给Task.WhenAll
List<Task> tasksToAwait = new List<Task> { appDataTask };
if (usersTask != null) tasksToAwait.Add(usersTask);
if (versionTask != null) tasksToAwait.Add(versionTask);

// 4. 等待所有任务完成
await Task.WhenAll(tasksToAwait);

// 5. 安全获取结果(await后用Result不会阻塞,也可以直接await任务)
AppData app = await appDataTask;
AppResponse response = app.ConvertData();

if (usersTask != null)
{
    DeployedUsers users = await usersTask;
    response.Users = users;
}

if (versionTask != null)
{
    VersionedApp versionedApp = await versionTask;
    response.version = versionedApp;
}

针对你优化后的OData场景的适配写法

如果是基于OData的扩展请求判断,同样用单独保存任务的方式,避免索引依赖:

bool? usersRequested = mosAppMetadataRequested?.Any(x => 
    x.PathToNavigationProperty.FirstSegment.Identifier.Equals(
        AAEConstants.ODataConstants.ODataExpandDeployedTo, 
        StringComparison.CurrentCultureIgnoreCase));
bool? isVersionRequested = mosAppMetadataRequested?.Any(x => 
    x.PathToNavigationProperty.FirstSegment.Identifier.Equals(
        AAEConstants.ODataConstants.ODataExpandAvailableTo, 
        StringComparison.CurrentCultureIgnoreCase));

// 启动主任务
Task<AppData> appDataTask = mosAdminApiClient.GetTitlePreviewAsync(identifierId, identifierName, version, token);

// 初始化可选任务
Task<Users> deployedToTask = null;
if (usersRequested.HasValue && usersRequested.Value)
{
    deployedToTask = GetDeployDataByTitleIdAsync(titleId: unifiedAppRequest.TitleId, token: token);
}

Task<VersionInfo> availableToTask = null;
if (isVersionRequested.HasValue && isVersionRequested.Value)
{
    availableToTask = GetAvailableToDataByTitleIdAsync(titleId: unifiedAppRequest.TitleId, token: token);
}

// 收集任务并等待
List<Task> tasks = new List<Task> { appDataTask };
if (deployedToTask != null) tasks.Add(deployedToTask);
if (availableToTask != null) tasks.Add(availableToTask);

await Task.WhenAll(tasks);

// 处理结果
UnifiedAppResponse response = (await appDataTask).ConvertPreviewToUnifiedAppResponse();

if (deployedToTask != null)
{
    response.DeployedTo = await deployedToTask;
}

if (availableToTask != null)
{
    response.AvailableTo = await availableToTask;
}

关键改进点

  • 绝不向Task.WhenAll传入null任务,只收集需要执行的非null任务
  • 单独保存每个可选任务的引用,不用列表索引定位,避免越界和类型错误
  • 用await获取任务结果,比直接访问Result更规范(即使任务已完成,await也不会有性能问题,且语义更清晰)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:29:54