如何在 Swift Tasks 中检查当前任务是否被取消(异步/等待)

问题描述 投票:0回答:1

为什么下面的代码不打印“cancelled”。我检查任务取消的方式是否错误?

import UIKit

class ViewController: UIViewController {
    
    private var task: Task<Void, Never>?
    
    override func viewDidLoad() {
        let task = Task {
            do {
                try await test()
            } catch {
                if Task.isCancelled {
                    print("cancelled in catch block..")
                }
                if let cancellationError = error as? CancellationError {
                    print("Task canceled..")
                }
            }
        }
        self.task = task
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
            task.cancel()
        }
    }
    
    func test() async throws {
        while true {
            if Task.isCancelled {
                print("cancelled..")
                throw URLError(.badURL)
            }
            // OUTPUT:
            // "cancelled.." will not be printed
            // "Task canceled.." will not be printed
            // "cancelled in catch block.." will not be printed
        }        
    }
}


但是,如果我将

if Task.isCancelled { print("cancelled in catch block..") }
放入 catch 块中,
cancelled in catch block..
将按预期执行。

swift async-await concurrency swift-concurrency
1个回答
0
投票

未打印“cancelled..”的原因是测试函数内的 Task.isCancelled 检查没有主动观察稍后由 task.cancel() 设置的取消状态。

要正确处理任务取消,您应该使用结构化并发的取消系统。你是对的,检查 catch 块内的 Task.isCancelled 确实反映了取消状态,因为它是在任务块内执行的。

import UIKit

class ViewController: UIViewController {
    
    private var task: Task<Void, Never>?
    
    override func viewDidLoad() {
        let task = Task {
            do {
                try await test()
            } catch {
                if Task.isCancelled {
                    print("cancelled in catch block..")
                }
                if let cancellationError = error as? CancellationError {
                    print("Task canceled..")
                }
            }
        }
        self.task = task
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
            task.cancel()
        }
    }
    
    func test() async throws {
        while true {
            try Task.checkCancellation()
            // Checking for cancellation using Task.checkCancellation()
            // This actively observes the task's cancellation status
            print("Checking for cancellation...")
        }
    }
}

通过在 test() 函数中使用 Task.checkCancellation() ,您可以正确检查任务块内的取消,并且在取消时,它将抛出 CancellationError 。然后,在 catch 块内,您可以适当地处理取消。

© www.soinside.com 2019 - 2024. All rights reserved.