首页 > 解决方案 > 调用 .cancel() 时,DispatchWorkItem 未终止函数

问题描述

我有一系列使用 Alamofire 在主函数中调用的函数列表中按顺序发出的 HTTP 请求runTask(),我希望能够停止这些请求。因此,我为我需要运行的每个任务设置了runTask()函数调用,并将工作项存储在一个数组中,如下所示:DispatchWorkItem

taskWorkItems.append(DispatchWorkItem { [weak self] in
    concurrentQueue!.async {
        runTask(task: task)
    }
})

然后,我迭代工作项数组并调用perform()函数,如下所示:

for workItem in taskWorkItems {
    workItem.perform()
}

最后,我的应用程序中有一个按钮,我想在点击时取消工作项,我有以下代码来实现这一点:

for workItem in taskWorkItems {
    concurrentQueue!.async {
        workItem.cancel()

        print(workItem.isCancelled)
    }
}

workItem.isCancelled打印到true; 但是,我在被调用的函数中设置了日志,runTask()即使workItem.cancel()被调用和workItem.isCancelled打印,我仍然看到函数正在执行true。我做错了什么,如何停止执行我的功能?

标签: iosswiftalamofiregrand-central-dispatchdispatchworkitem

解决方案


TLDR:如果任务尚未运行,调用取消将停止执行任务,但不会停止已经执行的任务。

由于有关此的苹果文档是陈旧的...

https://medium.com/@yostane/swift-sweet-bits-the-dispatch-framework-ios-10-e34451d59a86

A dispatch work item has a cancel flag. If it is cancelled before running, the dispatch queue won’t execute it and will skip it. If it is cancelled during its execution, the cancel property return True. In that case, we can abort the execution

//create the dispatch work item
var dwi2:DispatchWorkItem?
dwi2 = DispatchWorkItem {
    for i in 1...5 {
        print("\(dwi2?.isCancelled)")
        if (dwi2?.isCancelled)!{
            break
        }
        sleep(1)
        print("DispatchWorkItem 2: \(i)")
    }
}
//submit the work item to the default global queue
DispatchQueue.global().async(execute: dwi2!)

//cancelling the task after 3 seconds
DispatchQueue.global().async{
    sleep(3)
    dwi2?.cancel()
}

推荐阅读