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

不使用async/await实现多任务并行并等待全部完成的最优方案

现有代码的可运行性说明

你当前的写法确实可以实现两个任务并行执行,且等待两个任务完成后再执行Pack逻辑,在没有同步上下文的运行环境(比如.NET Core/.NET 5+控制台程序、ASP.NET Core服务)下可以正常运行,但存在明显的隐患和优化空间。

现有实现的潜在问题
  • 死锁风险:直接调用Task.Result会阻塞当前线程等待任务返回,如果你的代码运行在有同步上下文的环境(比如WPF、WinForms、旧版ASP.NET Framework)中,会触发死锁:任务执行完成后需要回到原同步上下文继续执行,但同步上下文的线程已经被.Result阻塞,导致双方互相等待。
  • 异常处理不友好:如果任意一个任务执行抛出异常,.Result会直接抛出包装后的AggregateException,你无法直接区分是哪个任务出错,也无法在异常抛出后做针对性的清理操作。
  • 等待逻辑冗余:你当前是在获取第一个Result时阻塞等待第一个任务,获取第二个Result时再阻塞等待第二个任务,虽然不影响最终结果,但不如统一等待两个任务完成的逻辑清晰。
更优的实现方案

核心优化点是:消除同步上下文捕获、统一等待所有任务、优化异常处理。
优化后的代码示例:

public string Export()
{
    var ifcFilePaths = ExportIfcFiles().ToList();
    // 启动两个并行任务
    Task<List<IfcToCsvGraphExportResult>> graphConverterResults = ConvertIfcToGraphData(ifcFilePaths);
    Task<List<IfcToGltfConversionResult>> gltfConverterResults = ConvertIfcToGltfData(ifcFilePaths);

    try
    {
        // 统一等待两个任务全部完成
        Task.WaitAll(graphConverterResults, gltfConverterResults);
    }
    catch (AggregateException ex)
    {
        // 可以展开内层异常,也可以单独判断每个任务的状态做针对性处理
        foreach (var innerEx in ex.Flatten().InnerExceptions)
        {
            // 按需处理异常,比如打日志、清理临时文件等
        }
        throw; // 或者返回自定义错误标识
    }

    List<string> folders = _outputFolderPacker.Pack(graphConverterResults.Result, gltfConverterResults.Result).ToList();
    return _zipPacker.Pack(folders);
}

private Task<List<IfcToCsvGraphExportResult>> ConvertIfcToGraphData(List<string> ifcFilePaths)
    => Task.Run(() => _ifcToCsvGraphExporter.Export(ifcFilePaths).ToList())
        .ConfigureAwait(false); // 配置不捕获同步上下文,大幅降低死锁风险

private Task<List<IfcToGltfConversionResult>> ConvertIfcToGltfData(List<string> ifcFilePaths)
    => Task.Run(() => _ifcToGltfConverter.Convert(ifcFilePaths).ToList())
        .ConfigureAwait(false); // 配置不捕获同步上下文
额外优化建议

如果你的两个转换操作是IO密集型(比如读写大IFC文件、调用外部转换工具),可以进一步把_ifcToCsvGraphExporter.Export和_ifcToGltfConverter.Convert改为异步实现,就算Export方法不能改为async,也能减少线程资源的浪费。如果是CPU密集型操作,当前的Task.Run实现已经是合理选择。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 13:36:05