在Swift并发编程中,Task.sleep()
和Task.yield()
都能暂停任务执行,但二者适用场景和机制有显著差异。以下通过示例和对比说明它们的核心区别。
1. Task.sleep():延迟执行
作用:暂停任务指定时间,期间允许其他任务运行,且不会阻塞底层线程。
特点:
- 可设置固定延迟时间(如秒、毫秒)。
- 若任务在休眠期间被取消,会抛出
CancellationError
。
典型场景:
- 用户输入防抖:延迟搜索请求,避免频繁触发。
func search(_ query: String) {
currentSearchTask?.cancel() // 取消之前的搜索任务
currentSearchTask = Task {
try await Task.sleep(for: .milliseconds(500)) // 等待用户停止输入
guard !Task.isCancelled else { return }
// 执行搜索逻辑
}
}
2. Task.yield():协作式让出执行权
作用:立即暂停当前任务,允许其他任务执行。
特点:
- 不保证暂停时间,若当前任务优先级最高,可能立即恢复执行。
- 不响应取消操作(无错误抛出)。
典型场景:
- 异步测试:确保其他任务优先执行后再验证结果。
func testIsLoading() async {
await withMainSerialExecutor {
let model = NumberFactModel {
await Task.yield() // 让出执行权,允许测试逻辑先运行
return "($0) is a good number."
}
let task = Task { await model.getFactButtonTapped() }
await Task.yield() // 等待模型内部逻辑执行
XCTAssertEqual(model.isLoading, true)
await task.value
}
}
3. 核心差异对比
特性 | Task.sleep() | Task.yield() |
---|---|---|
暂停时间 | 固定时长(可指定) | 不确定(可能立即恢复) |
响应取消 | 是(抛出错误) | 否 |
适用场景 | 延迟执行、轮询、限流 | 协作式任务切换、测试辅助 |
底层线程影响 | 不阻塞 | 不阻塞 |
总结
- 优先使用
Task.sleep()
:需要明确延迟或可取消的暂停操作(如用户输入防抖)。 - 谨慎使用
Task.yield()
:仅在需要强制让出执行权时使用(如测试或避免长时间阻塞其他任务)。 - 关键区别:
sleep
控制精确延迟,yield
仅协作式让出执行权,实际效果受优先级影响。
合理选择二者,可优化任务调度效率,避免资源浪费。