Aqui está um pequeno banco de testes mostrando duas tarefas que começam ao mesmo tempo, e a que for concluída primeiro cancela a outra:
func startTest() async throws {
Task { await test() }
try await Task.sleep(nanoseconds: 1 * NSEC_PER_SEC)
// comment out this next line to test the timeout
NotificationCenter.default.post(name: .init("Test"), object: nil)
}
func test() async {
let notificationTask = Task {
for await _ in NotificationCenter.default
.notifications(named: .init("Test"), object: nil)
.prefix(1) {}
print("Done waiting for the notification")
}
let timeoutTask = Task {
try await Task.sleep(nanoseconds: 5 * NSEC_PER_SEC)
notificationTask.cancel()
print("I timed out and cancelled the notification task")
}
await notificationTask.value
timeoutTask.cancel()
print("finished!")
}
Como você pode ver, a ideia é que ou recebamos a notificação em 5 segundos, caso em que o cronômetro de cinco segundos é cancelado, ou expiremos em 5 segundos, caso em que a espera pela notificação é cancelada.
Minha pergunta é: existe uma maneira mais clara de expressar isso? Tentei vários grupos de tarefas e formulações assíncronas, mas não encontrei nada. Talvez este seja o caminho "certo", mas de alguma forma irrita.
TaskGroup
await tg.next()
para aguardar o resultado do “vencedor da corrida”tg.cancelAll()
para cancelar as tarefas pendentes