在 Swift 5.5 中,在不支持并发的函数中等待两个任务完成的正确方法是什么?

Mac*_*wic 4 task async-await swift swift-concurrency

我有一个应用程序,可以对给定的字符串进行一些处理,这在 2Task秒内完成。在此期间我正在显示动画。当这些Task完成后,我需要隐藏动画。下面的代码可以工作,但看起来不太好。我相信有更好的方法来做到这一点?

let firTask = Task {
    /* Slow-running code */
}

let airportTask = Task {
    /* Even more slow-running code */
}

Task {
    _ = await firTask.result
    _ = await airportTask.result
    
    self.isVerifyingRoute = false
}
Run Code Online (Sandbox Code Playgroud)

mat*_*att 9

真正的问题不是滥用Task吗?正如您所发现的,任务本身并不是您可以等待的事情。如果目标是在后台运行缓慢的代码,请使用参与者。然后你可以用await干净地调用一个actor方法。

\n
let myActor = MyActor()\nawait myActor.doFirStuff()\nawait myActor.doAirportStuff()\nself.isVerifyingRoute = false\n
Run Code Online (Sandbox Code Playgroud)\n

但是,当我们与 \xe2\x80\x94\xc2\xa0 对话时,我们还需要确保我们位于主线程上self,而您的代码忽略了该操作。这是一个例子:

\n
actor MyActor {\n    func doFirStuff() async {\n        print("starting", #function)\n        await Task.sleep(2 * 1_000_000_000)\n        print("finished", #function)\n    }\n    func doAirportStuff() async {\n        print("starting", #function)\n        await Task.sleep(2 * 1_000_000_000)\n        print("finished", #function)\n    }\n}\nfunc test() {\n    let myActor = MyActor()\n    Task {\n        await myActor.doFirStuff()\n        await myActor.doAirportStuff()\n        Task { @MainActor in\n            self.isVerifyingRoute = false\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

一切都以正确的模式发生:耗时的事情发生在后台线程上,而调用self发生在主线程上。在我看来,处理主线程调用的一种更简洁的方法是使用一个@MainActor方法:

\n
func test() {\n    let myActor = MyActor()\n    Task {\n        await myActor.doFirStuff()\n        await myActor.doAirportStuff()\n        self.finish()\n    }\n}\n@MainActor func finish() {\n    self.isVerifyingRoute = false\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我认为这是优雅和清晰的。

\n