为什么此 swift async-await 代码会因继续泄漏而失败?

Why does this swift async-await code fails with leaked continuation?

我正在试验 Swift async-await 和 AsyncSequence 协议,

代码如下:

struct AsyncNumbers<Element: Numeric>: AsyncSequence {
    private let numbers: [Element]

    init(_ numbers: [Element]) {
        self.numbers = numbers
    }

    func makeAsyncIterator() -> AsyncNumberIterator {
        return AsyncNumberIterator(numbers)
    }
}

extension AsyncNumbers {
    struct AsyncNumberIterator: AsyncIteratorProtocol {
        private let numbers: [Element]
        private var index = -1

        init(_ numbers: [Element]) {
            self.numbers = numbers
        }

        mutating func next() async -> AsyncNumbers<Element>.Element? {
            index += 1
            return await withCheckedContinuation { [self] continuation in
                Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { timer in
                    guard index < numbers.count else {
                        continuation.resume(returning: nil)
                        timer.invalidate()
                        return
                    }
                    continuation.resume(returning: numbers[index])
                }
            }
        }
    }
}

func printNumbers() async {
    let numbers = AsyncNumbers([5,78,3,45,99,100,23,4,7,8,9])
    for await num in numbers {
        print("Number:", num)
    }
    print("End")
}

Task {
    await printNumbers()
}

此代码甚至在第一个数字打印到控制台之前就失败了,错误为 SWIFT TASK CONTINUATION MISUSE: next() leaked its continuation!

我不明白为什么我会在这里收到此错误,计时器块在 2 秒后仅调用一次,此处不会重复调用继续块,

有谁知道可能是什么问题?

提前谢谢你:)

正如一些正确评论的那样,问题是您使用 TimerConcurrency

Timer.scheduledTimer 需要运行循环才能工作。与主线程相反,辅助线程在您显式创建之前没有运行循环。

由于您是从 await 函数主体中的协程调用它,因此您的线程上下文是辅助线程。这意味着在您调用 Timer.scheduledTimer 时您没有运行循环,因此定时器回调将永远不会被调用,并且 - 根据周围代码的上下文 - Swift 正确地警告你你正在泄漏协程。