将多个事件添加到具有并发性的日历中



我创建了一个函数,使用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

我真的很累。

快照:快照

要查看任务已完成的所有状态消息,您必须对每个结果awaitprint进行

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()
}
}

最新更新