Swift闭包强烈捕获引用类型。
DispatchGroup是引用类型。
我的问题与以下代码有关:
func getUsername(onDone: @escaping (_ possUsername: String?) -> ())
{
//Post request for username that calls onDone(retrievedUsername)...
}
func getBirthdate(using username: String?, onDone: @escaping (_ possBday: String?) -> ())
{
//Post request for token that calls onDone(retrievedToken)...
}
func asyncTasksInOrder(onDone: @escaping (_ resultBDay: String?) -> ())
{
let thread = DispatchQueue(label: "my thread", qos: .userInteractive, attributes: [],
autoreleaseFrequency: .workItem, target: nil)
thread.async { [weak self, onDone] in
guard let self = self else {
onDone(nil)
return
}
let dg = DispatchGroup() //This is a reference type
var retrievedUsername: String?
var retrievedBday: String?
//Get username async first
dg.enter()
self.getUsername(onDone: {[weak dg](possUsername) in
retrievedUsername = possUsername
dg?.leave() //DG is weak here
})
dg.wait()
//Now that we've waited for the username, get bday async now
dg.enter()
self.getBirthdate(using: retrievedUsername, onDone: {[weak dg](possBday) in
retrievedBday = possBday
dg?.leave() //DG is also weak here
})
dg.wait()
//We've waited for everything, so now call the return callback
onDone(retrievedBday)
}
}
因此
asyncTasksInOrder(onDone:)
内部的两个闭包分别捕获了我的DispatchGroup dg
。.userInteractive
)?我之所以问这个特定问题,是因为在Android中扩展线程非常昂贵(如此昂贵,以至于JetBrains为Kotlin协程投入了大量资源)。 dg.notify(...)
如何参与所有这些工作?当dg.wait()
做同样的事情时,为什么还要有一个notify方法呢? 我觉得我对GCD的理解不是一帆风顺的,所以我要求树立信心。如果有什么要批评的话,也请批评。非常感谢您的帮助。
最佳答案
1)不,调度组是隐式捕获的。您甚至不需要捕获self
中的async
,因为GCD闭包不会引起保留周期。
2)没有保留周期。
3)实际上,您滥用DispatchGroup
来强制异步任务变得同步。
4)不,GCD非常轻巧。
5)DispatchGroup
的主要目的是在完成所有异步任务(例如,在重复循环中)时,不管顺序如何,将其转换为notify
。
更好的解决方案是嵌套异步任务。仅需完成两项任务,厄运金字塔就可以管理了。
func asyncTasksInOrder(onDone: @escaping (String?) -> Void)
{
let thread = DispatchQueue(label: "my thread", qos: .userInteractive, autoreleaseFrequency: .workItem)
thread.async {
//Get username async first
self.getUsername { [weak self] possUsername in
guard let self = self else { onDone(nil); return }
//Now get bday async
self.getBirthdate(using: possUsername) { possBday in
//Now call the return callback
onDone(possBday)
}
}
}
}