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

Swift异步环境下用Semaphore控制并发下载的问题求助

Swift异步批量下载:限制并发数并等待全部完成

在Swift Concurrency体系下,DispatchSemaphore的wait()是阻塞式调用,完全不适用于async函数——这会破坏异步非阻塞的设计原则,也是你遇到问题的核心原因。正确的方案是使用**TaskGroup**,它原生支持并发数限制,且能自动等待所有任务完成。

修正后的代码实现

func downloadAllFiles() async -> String {
    // 生成10个待下载URL
    let urls = Array(repeating: "https://google.com", count: 10)
    
    // 通过TaskGroup控制并发,最多同时运行3个任务
    await withTaskGroup(of: Void.self) { group in
        // 设置最大并发数
        group.maxConcurrentTaskCount = 3
        
        for url in urls {
            // 向任务组添加下载任务
            group.addTask {
                let web = await MWeb.call(url: url)
                // 此处可添加下载结果的处理逻辑(如本地存储、日志记录等)
            }
        }
        
        // TaskGroup会自动等待所有任务执行完毕,无需额外等待逻辑
    }
    
    return "所有文件下载完成"
}

关键细节说明

  • 替代DispatchSemaphore:TaskGroup的maxConcurrentTaskCount直接实现了并发数限制,完全符合Swift异步编程模型,不会阻塞线程。
  • 自动等待全部任务:withTaskGroup的闭包会一直等到所有添加的任务执行完毕才会退出,完美解决你需要等待10个文件全部处理完成的需求。
  • 优化任务管理:放弃Task.detached的独立任务创建方式,TaskGroup中的任务与当前上下文关联,优先级继承自父任务,不会出现"lower QoS thread"警告(如需指定优先级,可通过addTask(priority:)参数设置)。

扩展:收集下载结果

如果需要返回所有下载的成功/失败状态,可以调整TaskGroup的输出类型:

func downloadAllFiles() async -> [Result<Data, Error>] {
    let urls = Array(repeating: "https://google.com", count: 10)
    
    return await withTaskGroup(of: Result<Data, Error>.self) { group in
        group.maxConcurrentTaskCount = 3
        var results: [Result<Data, Error>] = []
        
        for url in urls {
            group.addTask {
                do {
                    let data = try await MWeb.call(url: url) // 假设MWeb.call抛出错误
                    return .success(data)
                } catch {
                    return .failure(error)
                }
            }
        }
        
        // 遍历收集所有任务结果
        for await result in group {
            results.append(result)
        }
        
        return results
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:35:44