使用Swift并发TaskGroup批量添加日历事件异常问题求助
解决EventKit结合TaskGroup批量添加事件的异常问题
核心原因
EKEventStore本身不是线程安全的,并发调用它的API(如事件保存)会触发底层资源竞争,导致部分任务未执行、数据异常或崩溃。同步版本正常是因为所有操作串行执行,避免了竞争;而直接用TaskGroup启动16个并发任务操作EventStore,刚好命中了线程安全问题。
正确优化方案
方案一:串行队列+TaskGroup管理任务
给EventStore的操作套一层串行队列,TaskGroup的子任务仅负责将保存任务提交到串行队列,既利用TaskGroup统一管理任务生命周期,又保证EventStore操作串行执行,避免竞争:
let eventStore = EKEventStore() private let eventQueue = DispatchQueue(label: "com.yourapp.eventkit.serial") func addCourses(_ courses: [Course]) async throws { try await withThrowingTaskGroup(of: Void.self) { group in for course in courses { group.addTask { try await withCheckedThrowingContinuation { continuation in self.eventQueue.async { do { let event = EKEvent(eventStore: self.eventStore) event.title = course.name event.startDate = course.startTime event.endDate = course.endTime event.calendar = self.eventStore.defaultCalendarForNewEvents try self.eventStore.save(event, span: .thisEvent) continuation.resume() } catch { continuation.resume(throwing: error) } } } } } try await group.waitForAll() } }
方案二:批量保存事件(更高效)
EventKit支持一次性批量保存多个事件,直接在内存中创建所有事件后提交,完全规避并发问题,性能比单条保存更优:
func addCoursesBatch(_ courses: [Course]) throws { let eventStore = EKEventStore() var events = [EKEvent]() for course in courses { let event = EKEvent(eventStore: eventStore) event.title = course.name event.startDate = course.startTime event.endDate = course.endTime event.calendar = eventStore.defaultCalendarForNewEvents events.append(event) } try eventStore.save(events, span: .thisEvent, commit: true) }
关于“循环放addTask闭包内正常”的原因
这种写法下,所有事件保存操作都在同一个Task的线程中串行执行,本质没有并发访问EventStore,因此不会触发线程安全问题,但此时TaskGroup确实失去了并行优化的意义,只是多了一层任务包装。
内容的提问来源于stack exchange,提问作者LiYanan2004
相关产品推荐
相关产品推荐

