前言
结构化并发 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 的基本结构
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 的创建与执行
let task = Task {
return await fetchUserData()
}
let highPriorityTask = Task(priority: .high) {
return await processImportantData()
}
let result = await task.value
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
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 {
let items = await fetchItems()
self.data = items
}
}
}
@MainActor
func demonstrateInheritance() {
let outerPriority = Task.currentPriority
Task {
assert(Task.currentPriority == outerPriority)
await MainActor.run {
}
}
}
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 {
await loadItems()
}
.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 {
self.data = "Updated from Task"
print(Task.currentPriority)
}
Task.detached {
await MainActor.run {
self.data = "Updated from detached"
}
print(Task.currentPriority)
}
}
}
对比详解表
| 特性 | Task { } | Task.detached { } |
|---|
| Actor 上下文 | ✅ 继承 | ❌ 不继承 |
| 任务优先级 | ✅ 继承 | ❌ 使用默认或指定值 |
| Task Local 值 | ✅ 继承 | ❌ 不继承 |
| 取消传播 | ⚠️ 不自动传播* | ❌ 完全独立 |
| 使用场景 | 大多数情况 | 需要隔离的后台工作 |
*注意:Task { } 创建的是非结构化任务,父任务取消不会自动取消子 Task,但会继承取消状态
何时使用 Task.detached
@MainActor
class ImageProcessor {
func processImage(_ image: UIImage) {
Task {
let processed = heavyImageProcessing(image)
self.displayImage(processed)
}
Task.detached(priority: .userInitiated) {
let processed = await self.heavyImageProcessing(image)
await MainActor.run {
self.displayImage(processed)
}
}
}
nonisolated func heavyImageProcessing(_ image: UIImage) async -> UIImage {
return image
}
}
class AnalyticsManager {
func trackEvent(_ event: String) {
Task.detached(priority: .background) {
await self.sendToServer(event)
}
}
}
@TaskLocal static var requestID: String?
func handleRequest() {
Self.requestID = "REQ-123"
Task {
print(Self.requestID)
}
Task.detached {
print(Self.requestID)
}
}
@MainActor
func userAction() {
Task.detached(priority: .background) {
await performMaintenance()
}
}
常见误用
@MainActor
class ViewModel {
var count = 0
func badExample() {
Task.detached {
await MainActor.run {
self.count += 1
}
}
}
}
func fetchData() async -> Data {
return await Task.detached {
await networkRequest()
}.value
}
class SearchController {
var searchTask: Task<Void, Never>?
func search(_ query: String) {
searchTask?.cancel()
searchTask = Task.detached {
Task.detached {
await performSearch(query)
}
}
}
}
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 的类型
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
}
}
func fetchAllData() async throws -> [Data] {
try await withThrowingTaskGroup(of: Data.self) {
group in
}
}
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()
}
let added = group.addTaskUnlessCancelled {
await maybeComputation()
}
if !added {
print("Group was cancelled, task not added")
}
for await value in group {
print("Got value: \(value)")
}
while let value = await group.next() {
print("Got value: \(value)")
}
let sum = await group.reduce(0, +)
group.cancelAll()
if group.i