我有一个带有异步方法的类.所有的方法都是最简单的:

class SomeClass {
   func someFunc(params: SomeParams, completion: ((SomeResult) -> ())?) {
      ... //some code where completion is called asynchronously, not only with DispatchQueue.async
   }
   ...//other methods
}

现在我需要添加一种可能性来取消这些任务,但SomeClass不负责它,所以这样的代码应该放在SomeClass以外的另一个类中.他们建议使用DispatchWorkItem,但如何正确地将这样的异步调用包装到它中?

注意:有关于如何用DispatchWorkItem替换DispatchQueue.global().async的问题和答案,而不是关于包装现有任务的问题和答案

推荐答案

我知道你已经解决了你的问题,但为了future 的读者,也为了回答这样一个标题问题:你是否可以将Swift中的异步任务包装到DispatchWorkItem中,使其可以取消?答案是,不,简单地将其包装在DispatchWorkItem中通常是不够的.正如documentation告诉我们的(强调加了):

取消会导致以后try 执行该工作项时立即返回.Cancellation does not affect the execution of a work item that has already begun.

如果您已经启动了cancel a DispatchWorkItem,则它只设置DispatchWorkItemisCancelled个属性,您可以在某个计算密集型 routine 中判断这些属性.但对于许多异步任务(如网络请求),这将是有限的实用程序.

更糟糕的是,DispatchWorkItem不太适合包装本身是异步的任务.DispatchWorkItem通常会在异步任务启动后立即完成工作项,而不是等待它完成(除非您做了一些笨拙和脆弱的事情,如使用信号量;以至于最好将其视为反模式).

您真的需要将取消逻辑合并到someFunc中.在历史上,我们经常达到Operation个子类(构建在GCD框架上),因为我们可以重写cancel来触发异步任务的取消.或者现在我们可以使用Swift concurrency’s async-await提供的自动抵消传播.或者,你似乎已经用Combine做到了这一点.

所以,归根结底,这取决于someFunc在做什么,但DispatchWorkItem的效用通常是有限的,尽管它(非常基本的)取消支持.

Swift相关问答推荐

并发访问SWIFT中数组的非重叠子范围

从AppKit打开SwiftUI设置

当计数大于索引时,索引超出范围崩溃

swift:只要框架名称中有一个带有框架名称的公共实体,就指定框架中公共 struct 的路径

使用序列初始化字符串的时间复杂度是多少?

如何隐藏集合视图中特定的单元格,以避免出现空白空间?

如何使用 Swift 在非本地函数中切换()一个 Bool?

在Equatable上引用运算符函数==要求Dictionary.Values符合Equatable

如何删除快速处理消息

memcpy 复制带偏移量的数组

在 struct 中的序列和非序列泛型函数之间进行 Select

如何为等待函数调用添加超时

创建 ViewModel 时 iOS 模拟器上的黑屏

无法增加系统镜像的大小

如何自己快速编写 Hashable 协议

Swift中的分段错误

在 ViewController 的 UICollectionView 中拉取刷新

如何在 SwiftUI 中创建带有图像的按钮?

修复 Swift 3 中的警告C-style for Statement is deprecated

自定义 Google 登录按钮 - iOS