我在Swift中有以下示例:
func call1() { call2() }
func call2() { call3() }
func call3() { call4() }
func call4() { call5() }
func call5() { print("finish") }
如果我想使call5((成为一个异步函数,是否必须将所有其他调用更改为async才能使call5(正常工作?
调用async
函数需要匹配的await
。要使其在同步上下文中工作,您需要将调用包装在任务中。
Task { await call5() }
这将在当前线程上生成一个并发任务。
以下是WWDC讨论,其中包含有关结构化并发的更多详细信息。https://developer.apple.com/videos/play/wwdc2021/10134/
您不必使它们都是async
,但您可以考虑这样做。具体来说,通过使它们都异步,您可以享受两个好处:
-
call1
的调用者现在可以知道整个序列何时完成,一直到call5
。 -
如果
call1
的调用方被取消,结构化并发将确保取消被自动传播到call5
。
因此,您有两个选项:
-
保持
call1
-call4
同步,但让call4
用Task { … }
调用call5
。如上所述,call1
的呼叫者失去了知道call5
何时完成的能力,并且您无法享受自动取消传播:func call1() { call2() } func call2() { call3() } func call3() { call4() } func call4() { Task { await call5() } } // opts out of structured concurrency func call5() async { … }
-
您可以使它们全部异步,这样
call1
的调用者就可以知道整个序列何时完成,并享受自动取消传播。func call1() async { await call2() } func call2() async { await call3() } func call3() async { await call4() } func call4() async { await call5() } func call5() async { … }
简而言之,这两种方法都不一定是对的或错的:这取决于call5
异步执行的操作。
此外,如果重构遗留代码库,您不必立即跳到选项2,而是可以从选项1开始,并随着时间的推移慢慢前进到选项2。请参阅WWDC 2021视频Swift并发:更新一个示例应用程序,了解如何随着时间的推移进行迁移。