Swift Concurrency的Task能否存入队列后再延迟启动?
解决方案
完全可以通过Swift Concurrency原生能力实现该需求,无需额外封装Operation对象。
核心注意点
Swift Concurrency中的Task一经创建就会立即进入调度队列执行,没有原生的暂停/挂起已创建Task再恢复执行的能力,因此你需要先存储待执行的任务闭包,而非提前初始化好的Task实例。
方案1:高优先级任务等待机制(适配重认证这类临时高优先级场景)
这是最贴合你提到的重新身份验证场景的实现方式:
- 维护一个可选的高优先级任务属性,存储当前正在执行的重认证等任务
- 所有普通业务任务执行前,先判断是否有正在执行的高优先级任务,存在则先等待其完成再执行自身逻辑
// 所属服务类的属性,存储当前正在执行的高优先级重认证任务 private var authRefreshTask: Task<Void, Error>? // 触发重认证时调用 func startAuthRefresh() { authRefreshTask = Task { // 执行重认证逻辑 try await authService.refreshToken() // 执行完成后置空 authRefreshTask = nil } } // 发起普通业务请求的统一入口 func fetchBusinessData() async throws { // 存在正在执行的重认证任务则先等待完成 if let refreshTask = authRefreshTask { try await refreshTask.value } // 重认证完成后再执行原业务请求 try await service.fetch(...) }
方案2:异步任务队列(适配需明确缓存一批任务、统一触发执行的场景)
如果你需要主动控制缓存任务的执行时机,可直接维护一个线程安全的待执行任务队列:
// 存储待执行的任务闭包,@Sendable保证跨线程调用安全 private var pendingTasks: [@Sendable () async throws -> Void] = [] // 添加任务到缓存队列,此时任务不会执行 func addPendingTask(_ task: @escaping @Sendable () async throws -> Void) { // 实际使用时建议加锁保证数组操作线程安全 pendingTasks.append(task) } // 高优先级任务完成后调用,执行所有缓存的任务 func runAllPendingTasks() { Task { // 取出所有任务并清空队列 let tasks = pendingTasks pendingTasks.removeAll() // 并发执行所有缓存任务 try await withThrowingTaskGroup(of: Void.self) { group in tasks.forEach { task in group.addTask { try await task() } } try await group.waitForAll() } } } // 使用示例 // 高优先级任务执行前添加任务到缓存 addPendingTask { try await service.fetch(...) } // 高优先级任务完成后触发批量执行 runAllPendingTasks()
补充说明
如果高优先级任务执行失败,你可以在等待逻辑中添加对应的错误处理,根据业务需要选择取消待执行任务、重试高优先级任务或者抛出错误给上层。
内容的提问来源于stack exchange,提问作者TruMan1
相关产品推荐
相关产品推荐

