ios 调用.cancel()时DispatchWorkItem未终止函数

gblwokeq  于 2023-02-14  发布在  iOS
关注(0)|答案(2)|浏览(125)

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

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,我仍然看到函数在执行。我做错了什么?如何停止函数的执行?

r8xiu3jd

r8xiu3jd1#

TLDR:调用cancel将停止执行尚未运行的任务,但不会停止已经在执行的任务。
既然苹果公司的文件已经过时了。
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()
}
djp7away

djp7away2#

我希望我的解决方案能帮助您。

var workItem:DispatchWorkItem?
workItem = DispatchWorkItem{
    while (true)
    {
       //Do you code as the loop
       usleep(10_000)
       // This condition is use to check the trigger that your code is done
       // The Loop must be break before you cancel
       if yourFinishedFlagIsDone {
               break
       }
    }
}
// Submit your work items and restore the finish flag
yourFinishedFlagIsDone = false
DispatchQueue.global().async(execute: workItem!)

// Add these lines of code to the event that you want to cancel the Dispatch Item
// Of Course, you need to enable your finish flag
yourFinishedFlagIsDone = true
DispatchQueue.global().async {
     workItem?.cancel()
}

实际上,这个解决方案只是一个变通方法。还有一点,你必须记住,你必须把DispatchWorkItem初始化放在你想要运行的事件的开头。当你调用workItem?.cancel()时,它会完全终止

相关问题