Swift Task 结构化并发

结构化并发: 一种组织并发任务的编程范式,强调任务之间的明确父子关系和生命周期管理,任务形成明确的父子关系树,父任务取消会自动传播到所有子任务, 作用域结束时也会自动等待所有子任务完成

非结构化并发: 更自由的并发任务管理,需要各自管理生命周期,可以存储任务引用,更加灵活

Swift并发中,结构化并发的另种方法: task group & async let

1. TaskGroup 话不多说上代码

swift 复制代码
struct TestTaskGroup {
    func test() async {
        print("Start")
        let result = try? await withThrowingTaskGroup(of: Int.self) { group in
            for i in 0 ..< 10 {
                group.addTask(priority: .high) {
                   let result = try await calculate(i)
                    return result
                }                
            }
            print("Task added")
            for try await result in group {
                print("Get result:\(result)")
            }
            print("Task ended")
            return value
        }
        print("End")
    }
    
    private func calculate(_ value: Int) async throws -> Int {
        print("Start calculate\(value)")
        try await Task.sleep(nanoseconds: UInt64(value * 5) * NSEC_PER_SEC)
        print("任务是否被取消 \(try Task.isCancelled)")
        print("calculate\(value) done")
        return value
    }
}

log输出:

可以看到任务在调用test的时候已经开始了 并且是并发执行的,group中的每个子任务都拥有返回值,并且group子任务返回值类型是一致的这点很有限制相对于async let 这点之后会讲, 如果我们想获取到所有子任务值之后应该怎么做呢 我们来改动一下代码如图:

这里上传了图1和图2 强调一下图1这种实现是不安全的 不推荐的

如上图我们所写要求group中的返回值是统一的例子中都是Int, 另外如果任何一个子任务抛出异常 整个taskGroup都会异常,所以一定要注意单个异常的捕获 如下异常处理:

swift 复制代码
private func calculate(_ value: Int) async throws -> Int {

        print("Start calculate\(value)")

        try? await Task.sleep(nanoseconds: UInt64(value * 2) * NSEC_PER_SEC)

        if value == 2 {

            print("Work\(value) throwing error")

            throw NSError(domain: "com.example.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "Task \(value) failed"])

        }

        print("calculate\(value) done")

        return value

    }
    
    func calculateTest() async {

        print("Start")

        do {

            let result = try await withThrowingTaskGroup(of: Int.self) { group in

                var value = 0

                for i in 0 ..< 3 {

                    group.addTask(priority: .high) {

                        do {

                            let result = try await calculate(i)

                            return result

                        } catch {

                            print("Error while processing results: \(error)")

                            throw error  // 重新抛出以取消整个任务组

                        }

                    }

                    

                }

                print("Task added")

                

                do {

                    for try await result in group {

                        value += result

                        

                        print("Get result:\(result) value is \(value)")

                    }

                } catch {

                    print("Error while processing results: \(error)")

                    throw error

                }

                

                print("Task ended")

                return value

            }

            print("End result is \(result)")

        } catch {

            print("Caught error: \(error)")

        }

    }

2. async let 是另外一种创建结构化并发子任务的方式,他的返回值类型不必是同样的类型,提高了灵活性

swift 复制代码
func asyncLet() async throws {
        print("Program started")
        async let result0 = calculate(0)
        async let result1 = calculate(1)  
        async let result2 = calculate(2)
        print("Tasks started concurrently")
        // 等待所有任务完成
        let (r0, r1, r2) = try await (result0, result1, result2)
        print("Program ended")

    }

从代码中可以看到,aysnc let 语法比较简洁,类似普通声明变量,只不过这里是一个异步函数,声明时立即开始并发执行,可以处理不同类型的返回值,需要明确使用try await 等待所有结果

3.两者对比:

  1. group可以动态的表达任务的数量 通过一个for循环来创建所有的任务,但是他要求所有返回值都是同一个类型
  2. asyn let提高了灵活性,但是对于动态任务组表达比较繁琐,比较适合处理固定数量的异步任务
相关推荐
闲云自留地5 小时前
云平台存储管理员:Cinder 创建挂载卷 + Swift 分布式存储原理
分布式·wpf·swift
2501_915909062 天前
SwiftUI 和 UIKit 怎么选?两代 UI 框架的适用范围
vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_915918412 天前
在Windows10上使用VSCode和Code Runner搭建Swift开发环境详细步骤
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
用户468104557243 天前
Swift 异步与并发
swift
安当加密03013 天前
PCI DSS 4.0与SWIFT CSP双合规:银行收单与跨境支付HSM部署实战
swift·hsm·密钥管理·pci dss·双合规
麒麟马4 天前
Swift 扩展归纳---Array (一)
ios·swift
2501_915106324 天前
Swift 4开发环境设置教程:xCode安装与Playground入门
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
东坡肘子6 天前
当 Mac mini 的价格不再 mini -- 肘子的 Swift 周报 #152
人工智能·swiftui·swift
2501_915106328 天前
第一次开发 iPhone App,可能碰到的问题,解决办法
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
末代iOS程序员华仔9 天前
iOS 5.6 条例解决方法
flutter·ios·swift