前言

结构化并发 vs 非结构化并发

┌─────────────────────────────────────────────────────────────────────┐
│                       Swift 并发模型                                 │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌────────────────────────────────────────────────────────────┐     │
│  │              结构化并发 (Structured Concurrency)            │     │
│  ├────────────────────────────────────────────────────────────┤     │
│  │                                                             │     │
│  │   async let    ─────┐                                       │     │
│  │                     ├──► 子任务生命周期 ≤ 父任务生命周期     │     │
│  │   TaskGroup    ─────┘                                       │     │
│  │                                                             │     │
│  │   特点:                                                    │     │
│  │   ✓ 自动取消传播                                           │     │
│  │   ✓ 自动等待子任务完成                                      │     │
│  │   ✓ 优先级继承                                              │     │
│  │   ✓ Task Local 值继承                                       │     │
│  │                                                             │     │
│  └────────────────────────────────────────────────────────────┘     │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────┐     │
│  │             非结构化并发 (Unstructured Concurrency)         │     │
│  ├────────────────────────────────────────────────────────────┤     │
│  │                                                             │     │
│  │   Task { }         ──► 继承上下文,手动管理生命周期          │     │
│  │                                                             │     │
│  │   Task.detached    ──► 完全独立,无继承                     │     │
│  │                                                             │     │
│  │   特点:                                                    │     │
│  │   ✗ 需要手动取消                                           │     │
│  │   ✗ 可能造成任务泄漏                                        │     │
│  │   ✓ 更灵活的生命周期控制                                    │     │
│  │                                                             │     │
│  └────────────────────────────────────────────────────────────┘     │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

选择指南速查表

场景推荐方式原因
并行获取多个独立数据async let简洁,自动等待
动态数量的并行任务TaskGroup灵活,可控
从同步代码启动异步Task { }继承上下文
后台独立任务Task.detached无上下文依赖
需要返回 Task 句柄Task { }可取消/等待
响应用户操作Task { @MainActor }UI 更新

Task基础

Task 的基本结构

// Task 的核心定义(简化)
struct Task<Success: Sendable, Failure: Error>: Sendable {
  
  // 创建并立即开始执行
  init(
  priority: TaskPriority? = nil,
  operation: @escaping @Sendable () async throws -> Success
  )
  // 获取结果
  var value: Success {
   get async throws }
  // 取消任务
  func cancel()
  // 检查是否已取消
  var isCancelled: Bool {
   get }
  }

Task 的创建与执行

// 1. 基本创建 - 立即开始执行
let task = Task {

return await fetchUserData()
}
// 2. 指定优先级
let highPriorityTask = Task(priority: .high) {

return await processImportantData()
}
// 3. 获取结果(需要 await)
let result = await task.value
// 4. 处理可能抛出错误的任务
let throwingTask = Task {

try await riskyOperation()
}
do {

let result = try await throwingTask.value
} catch {

print("Task failed: \(error)")
}

Task 优先级

// 优先级从高到低
enum TaskPriority: Comparable {

case high           // 用户交互,需要立即响应
case medium         // 默认优先级
case low            // 用户不直接等待的工作
case userInitiated  // 等同于 .high
case utility        // 长时间运行的任务
case background     // 维护性任务,用户无感知
}
// 使用示例
Task(priority: .high) {

// 处理用户点击
}
Task(priority: .background) {

// 预加载数据、清理缓存
}
// 获取当前任务优先级
Task {

print("Current priority: \(Task.currentPriority)")
}

Task 的继承特性

@MainActor
class ViewModel: ObservableObject {

@Published var data: [Item] = []
func loadData() {

// ✅ Task 继承 @MainActor 上下文
Task {

// 这里自动在 MainActor 上执行
let items = await fetchItems()
self.data = items  // ✅ 安全更新 UI
}
}
}
// 继承的内容:
// 1. Actor 上下文(如 @MainActor)
// 2. 任务优先级
// 3. Task Local 值
// 4. 取消状态(父任务取消时)
// 验证继承
@MainActor
func demonstrateInheritance() {

let outerPriority = Task.currentPriority
Task {

// 继承优先级
assert(Task.currentPriority == outerPriority)
// 继承 MainActor
await MainActor.run {

// 实际上已经在 MainActor 上了
}
}
}

Task 的生命周期

class DataManager {

private var currentTask: Task<[Item], Error>?
  func loadData() {
  
  // 取消之前的任务
  currentTask?.cancel()
  currentTask = Task {
  
  // 检查取消状态
  try Task.checkCancellation()
  let data = try await fetchData()
  // 长时间操作中定期检查
  for item in data {
  
  try Task.checkCancellation()
  await processItem(item)
  }
  return data
  }
  }
  func cancel() {
  
  currentTask?.cancel()
  currentTask = nil
  }
  deinit {
  
  currentTask?.cancel()
  }
  }

在 SwiftUI 中使用 Task

struct ContentView: View {

@State private var items: [Item] = []
@State private var isLoading = false
@State private var loadTask: Task<Void, Never>?
  var body: some View {
  
  List(items) {
   item in
  ItemRow(item: item)
  }
  .overlay {
  
  if isLoading {
  
  ProgressView()
  }
  }
  // ✅ 推荐:使用 .task 修饰符
  .task {
  
  await loadItems()
  }
  // ✅ 带 id 的 task,id 变化时自动取消并重启
  .task(id: selectedCategory) {
  
  await loadItems(for: selectedCategory)
  }
  // ⚠️ 手动管理时需要处理取消
  .onAppear {
  
  loadTask = Task {
  
  await loadItems()
  }
  }
  .onDisappear {
  
  loadTask?.cancel()
  }
  }
  func loadItems() async {
  
  isLoading = true
  defer {
   isLoading = false }
  do {
  
  items = try await api.fetchItems()
  } catch is CancellationError {
  
  // 任务被取消,正常情况
  } catch {
  
  // 处理其他错误
  }
  }
  }

Task对比

Task vs Task.detached 核心区别

@MainActor
class ViewModel {

var data: String = ""
func demonstrateDifference() {

// ========== Task(继承上下文)==========
Task {

// ✅ 继承 @MainActor,可以直接访问 self.data
self.data = "Updated from Task"
// ✅ 继承任务优先级
print(Task.currentPriority)  // 与外部相同
// ✅ 继承 Task Local 值
// ✅ 父任务取消时会收到取消信号
}
// ========== Task.detached(完全独立)==========
Task.detached {

// ❌ 不继承 @MainActor,需要显式切换
await MainActor.run {

self.data = "Updated from detached"
}
// ❌ 不继承优先级,使用默认值
print(Task.currentPriority)  // .medium
// ❌ 不继承 Task Local 值
// ❌ 父任务取消不影响此任务
}
}
}

对比详解表

特性Task { }Task.detached { }
Actor 上下文✅ 继承❌ 不继承
任务优先级✅ 继承❌ 使用默认或指定值
Task Local 值✅ 继承❌ 不继承
取消传播⚠️ 不自动传播*❌ 完全独立
使用场景大多数情况需要隔离的后台工作

*注意:Task { } 创建的是非结构化任务,父任务取消不会自动取消子 Task,但会继承取消状态

何时使用 Task.detached

// ✅ 场景1:CPU 密集型工作,避免阻塞 MainActor
@MainActor
class ImageProcessor {

func processImage(_ image: UIImage) {

// ❌ 错误:Task 继承 MainActor,会阻塞 UI
Task {

let processed = heavyImageProcessing(image)  // 阻塞主线程
self.displayImage(processed)
}
// ✅ 正确:detached 任务在后台执行
Task.detached(priority: .userInitiated) {

let processed = await self.heavyImageProcessing(image)
await MainActor.run {

self.displayImage(processed)
}
}
}
nonisolated func heavyImageProcessing(_ image: UIImage) async -> UIImage {

// CPU 密集型处理
return image
}
}
// ✅ 场景2:不需要继承上下文的独立工作
class AnalyticsManager {

func trackEvent(_ event: String) {

// 完全独立的后台任务,不需要任何上下文
Task.detached(priority: .background) {

await self.sendToServer(event)
}
}
}
// ✅ 场景3:明确不想继承 Task Local 值
@TaskLocal static var requestID: String?
func handleRequest() {

Self.requestID = "REQ-123"
Task {

print(Self.requestID)  // "REQ-123" - 继承
}
Task.detached {

print(Self.requestID)  // nil - 不继承
// 这里开始一个全新的追踪链
}
}
// ✅ 场景4:需要指定不同的优先级
@MainActor
func userAction() {

// MainActor 通常是高优先级
Task.detached(priority: .background) {

// 明确使用低优先级,不继承外部的高优先级
await performMaintenance()
}
}

常见误用

// ❌ 误用1:在 detached 中直接访问 actor 隔离的属性
@MainActor
class ViewModel {

var count = 0
func badExample() {

Task.detached {

// ❌ 编译错误:count 是 MainActor 隔离的
// self.count += 1
// ✅ 必须显式切换
await MainActor.run {

self.count += 1
}
}
}
}
// ❌ 误用2:不必要的 detached
func fetchData() async -> Data {

// ❌ 这里没必要用 detached
return await Task.detached {

await networkRequest()
}.value
// ✅ 直接调用即可
// return await networkRequest()
}
// ❌ 误用3:期望 detached 自动取消
class SearchController {

var searchTask: Task<Void, Never>?
  func search(_ query: String) {
  
  searchTask?.cancel()
  // ❌ detached 任务取消后,内部的其他 detached 不会被取消
  searchTask = Task.detached {
  
  Task.detached {
  
  // 即使外部任务取消,这里也不会取消
  await performSearch(query)
  }
  }
  }
  }

TaskGroup

TaskGroup 基础

// TaskGroup 用于动态数量的并行任务
func fetchAllUserData(userIDs: [Int]) async throws -> [User] {

try await withThrowingTaskGroup(of: User.self) {
 group in
// 添加任务到组
for id in userIDs {

group.addTask {

try await fetchUser(id: id)
}
}
// 收集结果
var users: [User] = []
for try await user in group {

users.append(user)
}
return users
}
}

TaskGroup 的类型

// 1. 不抛出错误的 TaskGroup
func processItems(_ items: [Item]) async -> [Result] {

await withTaskGroup(of: Result.self) {
 group in
for item in items {

group.addTask {

await process(item)
}
}
var results: [Result] = []
for await result in group {

results.append(result)
}
return results
}
}
// 2. 可抛出错误的 ThrowingTaskGroup
func fetchAllData() async throws -> [Data] {

try await withThrowingTaskGroup(of: Data.self) {
 group in
// ...
}
}
// 3. 丢弃结果的 TaskGroup(Swift 5.9+)
func fireAndForget(_ tasks: [() async -> Void]) async {

await withDiscardingTaskGroup {
 group in
for task in tasks {

group.addTask {

await task()
}
}
// 自动等待所有任务完成,不收集结果
}
}

TaskGroup 的核心方法

await withTaskGroup(of: Int.self) {
 group in
// ========== 添加任务 ==========
// 基本添加
group.addTask {

await computeValue()
}
// 指定优先级
group.addTask(priority: .high) {

await urgentComputation()
}
// 条件添加(Swift 5.9+)
let added = group.addTaskUnlessCancelled {

await maybeComputation()
}
if !added {

print("Group was cancelled, task not added")
}
// ========== 收集结果 ==========
// 方式1:for-await-in 循环
for await value in group {

print("Got value: \(value)")
}
// 方式2:使用 next()
while let value = await group.next() {

print("Got value: \(value)")
}
// 方式3:reduce
let sum = await group.reduce(0, +)
// ========== 取消控制 ==========
// 取消所有子任务
group.cancelAll()
// 检查是否已取消
if group.i