如何使用 Swift 并发限制并发(如 `maxConcurrentOperationCount`)?

How to constrain concurrency (like `maxConcurrentOperationCount`) with Swift Concurrency?

我正在尝试执行一系列网络请求,并希望在新的 Swift 并发系统中限制并发任务的数量。对于操作队列,我们​​将使用 maxConcurrentOperationCount. In Combine, flatMap(maxPublishers:_:)。新 Swift 并发系统中的等价物是什么?

例如,它不是很相关,但请考虑:

func download() async throws {
    try await withThrowingTaskGroup(of: Void.self) { group in
        for i in 0..<20 {
            let source = sourceUrl(for: i)
            let destination = destinationUrl(for: i)

            group.addTask {
                let (url, _) = try await self.session.download(from: source)
                try? FileManager.default.removeItem(at: destination)
                try FileManager.default.moveItem(at: url, to: destination)
            }
        }

        try await group.waitForAll()
    }
}

这导致所有请求 运行 同时发生:

URLSession 不尊重 httpMaximumConnectionsPerHost 这一事实很有趣,但不是这里的突出问题。更一般地说,我正在寻找如何并行地限制一系列异步任务 运行 中的并发度。

可以在达到一定计数后在循环内插入一个 group.next() 调用,例如:

func download() async throws {
    try await withThrowingTaskGroup(of: Void.self) { group in
        for i in 0..<20 {
            let source = sourceUrl(for: i)
            let destination = destinationUrl(for: i)

            if i >= 6 {                                                     // max of six at a time
                try await group.next()
            }

            group.addTask {
                let (url, _) = try await self.session.download(from: source)
                try? FileManager.default.removeItem(at: destination)
                try FileManager.default.moveItem(at: url, to: destination)
            }
        }

        try await group.waitForAll()
    }
}

结果一次不超过六个: