为什么此 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 秒后仅调用一次,此处不会重复调用继续块,
有谁知道可能是什么问题?
提前谢谢你:)
正如一些正确评论的那样,问题是您使用 Timer
和 Concurrency
。
Timer.scheduledTimer
需要运行循环才能工作。与主线程相反,辅助线程在您显式创建之前没有运行循环。
由于您是从 await
函数主体中的协程调用它,因此您的线程上下文是辅助线程。这意味着在您调用 Timer.scheduledTimer
时您没有运行循环,因此定时器回调将永远不会被调用,并且 - 根据周围代码的上下文 - Swift 正确地警告你你正在泄漏协程。
我正在试验 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 秒后仅调用一次,此处不会重复调用继续块,
有谁知道可能是什么问题?
提前谢谢你:)
正如一些正确评论的那样,问题是您使用 Timer
和 Concurrency
。
Timer.scheduledTimer
需要运行循环才能工作。与主线程相反,辅助线程在您显式创建之前没有运行循环。
由于您是从 await
函数主体中的协程调用它,因此您的线程上下文是辅助线程。这意味着在您调用 Timer.scheduledTimer
时您没有运行循环,因此定时器回调将永远不会被调用,并且 - 根据周围代码的上下文 - Swift 正确地警告你你正在泄漏协程。