我创建了一个函数,使用EventKit将我的课程事件添加到日历应用程序中。
在学习了快速并发之后,我想更新我的代码以使进度更快,即使用分离的任务或TaskGroup来添加这些事件。
在不分离任务或任务组的情况下同步代码:
func export_test() {
Task.detached {
for i in 0...15 {
print("Task (i): Start")
let courseEvent = EKEvent(eventStore: eventStore)
courseEvent.title = "TEST"
courseEvent.location = "TEST LOC"
courseEvent.startDate = .now
courseEvent.endDate = .now.addingTimeInterval(3600)
courseEvent.calendar = eventStore.defaultCalendarForNewEvents
courseEvent.addRecurrenceRule(EKRecurrenceRule(recurrenceWith: .daily, interval: 1, end: nil))
do {
try eventStore.save(courseEvent, span: .futureEvents)
} catch { print(error.localizedDescription) }
print("Task (i): Finished")
}
}
}
使用TaskGroup
:执行相同操作
func export_test() {
Task.detached {
await withTaskGroup(of: Void.self) { group in
for i in 0...15 {
group.addTask {
print("Task (i): Start")
let courseEvent = EKEvent(eventStore: eventStore)
courseEvent.title = "TEST"
courseEvent.location = "TEST LOC"
courseEvent.startDate = .now
courseEvent.endDate = .now.addingTimeInterval(3600)
courseEvent.calendar = eventStore.defaultCalendarForNewEvents
courseEvent.addRecurrenceRule(EKRecurrenceRule(recurrenceWith: .daily, interval: 1, end: nil))
do {
try eventStore.save(courseEvent, span: .futureEvents)
} catch { print(error.localizedDescription) }
print("Task (i): Finished")
}
}
}
}
}
TaskGroup
版本的输出:
Task 0: Start
Task 1: Start
Task 2: Start
Task 4: Start
Task 3: Start
Task 5: Start
Task 6: Start
Task 7: Start
Task 0: Finished
Task 8: Start
Task 1: Finished
Task 9: Start
有时,只会完成一些任务,而其他任务则不会,甚至从未启动(我创建了16个任务,但在本例中只打印了9个)。有时,可以添加所有这些事件。
在我看来,我在TaskGroup
中创建了16个子任务。
每个子任务将向日历中添加一个事件我认为通过这种方式,我可以充分利用多核性能(也许事实并非如此。)
如果我把for循环放在group.addTask
闭包中,它总是会有预期的结果,但这样,我们只有一个循环,所以可能不再需要TaskGroup
。
我真的很累。
快照:快照
要查看任务已完成的所有状态消息,您必须对每个结果await
和print
进行
func export_test() {
Task.detached {
await withTaskGroup(of: String.self) { group in
for i in 0...15 {
group.addTask {
print("Task (i): Start")
let courseEvent = EKEvent(eventStore: eventStore)
courseEvent.title = "TEST"
courseEvent.location = "TEST LOC"
courseEvent.startDate = .now
courseEvent.endDate = .now.addingTimeInterval(3600)
courseEvent.calendar = eventStore.defaultCalendarForNewEvents
courseEvent.addRecurrenceRule(EKRecurrenceRule(recurrenceWith: .daily, interval: 1, end: nil))
do {
try eventStore.save(courseEvent, span: .futureEvents)
} catch { print(error.localizedDescription) }
return "Task (i): Finished"
}
}
for await taskStatus in group {
print(taskStatus)
}
}
}
}
经过长时间对代码的各个方面的研究。我发现问题出在try eventStore.save(courseEvent, span: .futureEvents)
上。
或者,我使用try eventStore.save(..., span: ..., commit: false)
和eventStore.commit()
来解决问题。
我认为这是由数据竞赛引起的,因为我使用的是快速并发。当一个事件正在保存时,另一个事件调用save
方法再次保存,导致数据冲突(只是我的猜测)
幸运的是,为了解决这个问题,我们可以稍后使用eventStore.commit()
提交一批事件,以避免数据冲突。结果是我所期望的!!
经过优化后,该功能的性能提高了25%(准确地说,提高了136ms)。(哈哈。完美。)
最终代码(Swift 5.7中):
func export_test() {
Task.detached {
await withTaskGroup(of: Void.self) { group in
for i in 0...15 {
group.addTask {
print("Task (i): Start")
let courseEvent = EKEvent(eventStore: eventStore)
courseEvent.title = "TEST"
courseEvent.location = "TEST LOC"
courseEvent.startDate = .now
courseEvent.endDate = .now.addingTimeInterval(3600)
courseEvent.calendar = eventStore.defaultCalendarForNewEvents
courseEvent.addRecurrenceRule(EKRecurrenceRule(recurrenceWith: .daily, interval: 1, end: nil))
try eventStore.save(courseEvent, span: .futureEvents, commit: false)
}
}
}
eventStore.commit()
}
}