Я создаю значения асинхронно, используя Task.sleep или DispatchQueue.asyncAfter. Если я вызываю Finish() после получения последнего значения (i == 5), Playground аварийно завершает работу с сообщением «выполнение остановлено с неожиданным состоянием».
Если я закомментирую Finish(), сбой исчезает, но deinit никогда не вызывается.
Вот упрощенная версия моего кода:
Код: Выделить всё
import Foundation
class Demo {
func getAsyncStream(_ doUseTask: Bool = false) -> AsyncStream {
AsyncStream { continuation in
for i in 1...5 {
if doUseTask {
Task {
try await Task.sleep(for: .seconds(i))
continuation.yield(i)
// What I am thinking, Ideally I have to do this after yield is succesful, but there is no callBack
if i == 5 {
// If I comment this out, the error disappears but deinit is not printed;
// otherwise, deinit prints and the error still exists.
continuation.finish()
}
}
} else {
DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(i)) {
continuation.yield(i)
if i == 5 {
// If I comment this out, the error disappears but deinit is not printed;
// otherwise, deinit prints and the error still exists.
continuation.finish()
}
}
}
}
}
}
init() { print("initialised") }
deinit { print("deinitialised") }
}
do {
let demo = Demo()
for await value in demo.getAsyncStream(true) {
print(value)
}
}
Вызов Finish() приводит к сбою Playground.
Удаление Finish() предотвращает сбой, но deinit никогда не печатается.
Вопросы:
Почему вызов Finish() от параллельных производителей вызывает сбой?
Почему i == 5 не является безопасный способ определить, когда завершить поток?
Каков правильный шаблон безопасного вызова Finish() при асинхронном создании значений?
Это поведение характерно для Swift Playgrounds или оно будет наблюдаться и в реальном приложении?
Подробнее здесь: https://stackoverflow.com/questions/798 ... -dispatchq
Мобильная версия