897 字
4 分钟
Swift Task Group
Task
定义:
Task
是 Swift 结构化并发模型中的基本工作单元,代表一个异步操作的执行。所有异步代码(如async
函数)都运行在某个Task
中。特点:
- 层级结构:任务可以形成父子关系(父任务与子任务),构成任务树。
- 隔离性:任务之间默认相互隔离,但可通过
actor
安全共享状态。 - 取消机制:支持协作式取消(通过
Task.isCancelled
或Task.checkCancellation()
检查)。 - 优先级:可指定优先级(如
.high
,.low
),子任务默认继承父任务的优先级。
创建方式:
- 隐式创建:使用
async let
创建子任务(自动绑定到当前任务)。async let photo1 = downloadPhoto(named: "photo1") let photos = await [photo1, photo2, photo3]
- 显式创建:
- 结构化任务:通过
TaskGroup
添加子任务。 - 非结构化任务:使用
Task.init
(继承当前上下文)或Task.detached
(独立上下文)。let task = Task { await someAsyncWork() } let result = await task.value
- 结构化任务:通过
- 隐式创建:使用
关键行为:
- 任务挂起时(遇到
await
),线程可能被其他任务复用。 - 父任务取消时,所有子任务自动取消。
- 任务结果通过
await
获取,错误通过try
传递。
- 任务挂起时(遇到
TaskGroup
定义:
TaskGroup
用于显式管理一组子任务,支持动态添加任务并控制并发行为,是结构化并发的核心工具。用途:
- 并行执行多个独立任务(如批量下载资源)。
- 收集子任务结果或处理完成顺序。
使用步骤:
- 创建任务组:通过
withTaskGroup
或withThrowingTaskGroup
(支持错误传递)。 - 添加子任务:使用
group.addTask
。 - 等待结果:通过
for await
遍历结果或直接收集。
- 创建任务组:通过
示例:
let photos = await withTaskGroup(of: Optional<Data>.self) { group in let photoNames = await listPhotos(inGallery: "Summer Vacation") for name in photoNames { let added = group.addTaskUnlessCancelled { guard !Task.isCancelled else { return nil } return await downloadPhoto(named: name) } guard added else { break } } var results: [Data] = [] for await photo in group { if let photo { results.append(photo) } } return results }
特点:
- 结构化生命周期:任务组确保所有子任务在闭包退出前完成。
- 动态任务数量:可循环内动态添加任务。
- 取消传播:取消任务组会取消所有子任务。
- 结果顺序:子任务完成顺序不确定,但结果可按完成顺序收集。
与
async let
的区别:async let
TaskGroup
任务数量 固定(编译时确定) 动态(运行时确定) 结果收集 需显式列出所有 async let
通过循环遍历完成的任务 适用场景 少量已知并行任务 批量或动态任务(如下载)
注意事项
结构化并发:
通过任务父子关系确保:- 子任务在父任务退出前完成。
- 错误和取消自动传播。
- 避免资源泄漏(如未等待的任务)。
取消处理:
- 在任务中定期检查
Task.isCancelled
或调用Task.checkCancellation()
。 - 清理资源(如关闭网络连接)后退出。
- 在任务中定期检查
线程安全:
- 跨任务共享数据需使用
Sendable
类型(如值类型、不可变类、actor
)。 - 避免在任务间直接共享可变引用类型。
- 跨任务共享数据需使用
性能权衡:
- 并行任务数量受系统资源限制(如 CPU 核心数)。
- 过多任务可能导致线程竞争,需合理控制并发度。
总结
Task
是并发的基本单元,用于封装异步操作,支持层级管理和取消。TaskGroup
提供结构化方式管理动态子任务,适合批量并行工作。- 二者共同构建 Swift 的安全并发模型,通过编译时检查(如
Sendable
)和运行时机制(如任务取消)避免常见并发问题。
Swift Task Group
https://blog.lpkt.cn/posts/swift-task-group/