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

如何限制Swift TaskGroup中同时执行的并发任务数量

Swift 基于TaskGroup限制并发数的实现方法

核心实现逻辑

Swift 原生TaskGroup本身没有暴露设置最大并发数的接口,要手动控制并发量不需要引入第三方库,只要调整任务入组的节奏即可:

  • 不要在初始化任务组时一次性把所有待执行任务全部入组
  • 初始阶段仅向任务组添加和设定的最大并发数等量的任务
  • 后续每收到1个任务完成的返回结果,立刻从待处理任务队列里取1个新任务补入组
  • 整个执行周期内,同时处于运行状态的任务数会始终维持在你设定的阈值以内,不会出现一次性触发上百个下载请求的问题

适配图片下载场景的改造代码

以你需要的「最多同时下载10张图片」的需求为例,改造后的代码如下:

// 最大并发下载数量,可根据需求自行调整
let maxConcurrentDownloadCount = 10

func loadImageData(for assets: [PHAsset]) {
    Task {
        do {
            let imagesData = try await withThrowingTaskGroup(of: (id: String, data: Data).self) { group in
                // 记录当前已经加入任务组的资源索引
                var currentIndex = 0
                let totalCount = assets.count
                
                // 第一步:先把初始的最大并发数等量的任务加入组
                while currentIndex < min(maxConcurrentDownloadCount, totalCount) {
                    let asset = assets[currentIndex]
                    group.addTask {
                        return (id: asset.localIdentifier, data: try await self.imageData(for: asset))
                    }
                    currentIndex += 1
                }
                
                var dictionary = [String: Data]()
                // 第二步:每完成一个任务,就补一个新任务进组
                for try await item in group {
                    dictionary[item.id] = item.data
                    print("Downloaded \(dictionary.count) of \(totalCount)")
                    
                    // 还有未处理的资源时,补加新任务
                    if currentIndex < totalCount {
                        let asset = assets[currentIndex]
                        group.addTask {
                            return (id: asset.localIdentifier, data: try await self.imageData(for: asset))
                        }
                        currentIndex += 1
                    }
                }
                
                return assets.compactMap { dictionary[$0.localIdentifier] }
            }
            
            print("Done")
        } catch {
            print(error)
        }
    }
}

func imageData(for asset: PHAsset) async throws -> Data {
    // 此处保留原来的PHImageManager适配async/await的逻辑即可
}

额外说明

  • 这种实现完全是Swift并发框架原生支持的写法,没有用到任何黑魔法,系统依然会根据CPU、网络状态自动调度任务,只是把任务入组的节奏从「一次性全塞」改成了「完成一个补一个」
  • 并发数不要设置得过高,图片下载场景建议根据网络环境设置在4~20之间即可,过高的并发反而会因为带宽抢占、系统线程调度开销导致整体下载速度变慢
  • 现有逻辑完全兼容Swift并发的取消机制,父任务取消时任务组内所有正在执行和等待的任务都会被自动取消,不需要额外处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 16:27:47