下面是一个小测试平台,它显示了两个同时开始的任务,先完成的会取消另一个:

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!")
}

如您所见,我们的 idea 是要么在5秒内收到通知,在这种情况下取消5秒计时器,要么在5秒内超时,在这种情况下,等待通知的情况被取消.

我的问题是:有没有更简洁的方式来表达这一点?我try 了各种任务组和异步LET配方,但什么都没有想出来.也许这是"正确的"方式,但不知何故,这让人恼火.

推荐答案

  1. TaskGroup
  2. 把你所有的"赛跑"任务都加进go (它们可以超过2个!)
  3. 拨打await tg.next()等待"胜利者"的结果
  4. 拨打tg.cancelAll()取消未完成的任务
  5. ???
  6. 利润!
import Foundation

func startTest() async throws {
    Task { try 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 throws {
    try await withThrowingTaskGroup(of: Void.self) { group in
        group.addTask { // formerlynotificationTask
            for await _ in NotificationCenter.default
                .notifications(named: .init("Test"), object: nil)
                .prefix(1) {}
            print("Done waiting for the notification")
        }
        
        group.addTask { // formerly "timeoutTask"
            try await Task.sleep(nanoseconds: 5 * NSEC_PER_SEC)
            print("I timed out and cancelled the notification task")
        }
        
        try await group.next() // Wait for the first completed task
        group.cancelAll() // Cancel the rest
    }
    print("finished!")
}

try await startTest()

Swift相关问答推荐

纹理资源加载问题(图像解码失败)

阴影动画的动画不流畅

我正在try 通过代码设置节中页眉和页脚的高度,但它不起作用

如何避免切换视图递归onChange调用SwiftUI

如何偏移HStack中的视图,但仍然约束框架以与偏移匹配?

如何使用可搜索在搜索栏中搜索包括>或<?

如何使用模型在 SwiftUI 的列表中进行搜索

如何测试可选 struct 的协议一致性

如何从数据中读取以空结尾的字符串?

对齐时如何避免图像尺寸缩小

使用协议捕获 SwiftUI 视图

使用 Swiftui 水平修剪 Shape()

不要从 NumberFormatter 获取货币符号

我们如何显示关于 UITextField 是 xCode Swift 的建议?

如何让 UIKit 挤压你的视图,使其适合屏幕

What is "SwiftPM.SPMRepositoryError error 5"?

在swift 3中将文件保存在文档目录中?

是否可以在 Swift 中创建通用闭包?

使用 Swift 以编程方式自定义 UITableViewCell

Switch 语句中的字符串:String不符合协议IntervalType