一个类型擦除的自我取消任务,使使用 Swift 并发更容易
任何任务
一个小型的 Swift 包引入了一种类型,为 Swift 提供了类型擦除,这使得它变得非常容易
在删除泛型后存储在集合中。AnyTask
Task
此外,当它被销毁时,一个会自行取消,让您无需手动取消任何
销毁 S 集合时的挂起任务。如果您愿意,也可以选择退出此行为。AnyTask
AnyTask
最后,如果取消尝试在以下情况下发生取消尝试,还可以将 配置为在调试模式下使断言失败
任务已取消。AnyTask
为什么这很有用
很容易忘记取消 Swift ,即使没有任何东西保留对它的引用,它也会继续运行。
除非您正在创建“即发即弃”任务,否则您可能希望确保在它不再时将其取消
需要(即当拥有类被销毁时)。Task
这意味着您必须手动将一个存储在某个地方,以便以后可以取消它,除非它是
在集合中存储不同类型的 S 非常困难,因为它们可以专门用于不同类型的:Task
Task
let taskA = Task<Bool, Never> { // code to return a Bool }
let taskB = Task<Void, Error> { // code that doesn't return a value but can throw }
let tasks = [taskA, taskB] // This code won't compile
这意味着您需要为每个可能的专用类型使用不同的集合,或者每种类型都需要不同的属性,然后确保记住在 中正确取消它们。Task
Task
deinit
AnyTask
类型擦除 s,这意味着您可以将创建的每个任务存储在单个集合(或集合)中
并且它还会在集合被销毁时自动取消集合中的所有任务,因为当集合被取消时会自行取消:Task
AnyTask
var tasks: [AnyTask] = []
Task<Bool, Never> {}.store(in: &tasks)
Task<Void, Error> {}.store(in: &tasks)
// When `tasks` is destroyed, the `AnyTask`s will automatically cancel the underlying type-erased `Task`s.
用法
擦除Task
您可以从 Swift 手动创建,但使用便利功能来存储更简单
在 s 的集合中:AnyTask
Task
Task
AnyTask
var tasks: [AnyTask] = []
Task {
// Async task code
}.store(in: &tasks)
You can also do the same thing with a set of s:AnyTask
var tasks: Set<AnyTask> = []
Task {
// Async task code
}.store(in: &tasks)
If you want to you can also make a call to erase a task explicitly:
let task: AnyTask = Task {
// Async task code
}.erased()
Or you can also create an manually from a :AnyTask
Task
let task = Task {
// Async task code
}
let anyTask = AnyTask(task)
Setting options
Wherever you are able to erase a to you are able to override the default options that the is
configured with.Task
AnyTask
AnyTask
Task {}.store(in: &tasks, options: [.assertOnOverCancellation])
Task {}.erased(options: [])
AnyTask(Task {}, options: [])
You can see a full list of available in code.Options
Cancelling a task
You can still manually check if an is cancelled by checking the property:AnyTask
isCancelled
var tasks: [AnyTask] = []
let task: AnyTask = Task {}.store(in: &tasks)
task.isCancelled
You can also explicitly cancel a task by calling :cancel()
var tasks: [AnyTask] = []
let task: AnyTask = Task {}.store(in: &tasks)
task.cancel()