关闭和其他 GCD 问题中的 Weak DispatchGroup
Weak DispatchGroup in closures and other GCD questions
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:)
中的两个闭包每个捕获 dg
,我的 DispatchGroup。
- 还有必要抓我的调度组吗?
- 如果我不捕获它,我怎么知道我有一个保留周期?
- 如果调度组在其中一个回调执行期间消失了怎么办?它会因为等待而蒸发吗?
- 像这样经常实例化一个 DispatchQueue(忽略
.userInteractive
)是否不必要地昂贵?我问这个特定的问题是因为在 Android 中旋转线程非常昂贵(如此昂贵以至于 JetBrains 将大量资源用于 Kotlin 协程)。
dg.notify(...)
如何发挥所有这些作用?为什么在 dg.wait()
做同样的事情时还要有一个通知方法?
我觉得我对 GCD 的理解不是万无一失的,所以我想建立一些信心。有什么可以批评的也请批评指正。非常感谢您的帮助。
1) 不,调度组是隐式捕获的。您甚至不需要在 async
中捕获 self
,因为 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)
}
}
}
}
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:)
中的两个闭包每个捕获 dg
,我的 DispatchGroup。
- 还有必要抓我的调度组吗?
- 如果我不捕获它,我怎么知道我有一个保留周期?
- 如果调度组在其中一个回调执行期间消失了怎么办?它会因为等待而蒸发吗?
- 像这样经常实例化一个 DispatchQueue(忽略
.userInteractive
)是否不必要地昂贵?我问这个特定的问题是因为在 Android 中旋转线程非常昂贵(如此昂贵以至于 JetBrains 将大量资源用于 Kotlin 协程)。 dg.notify(...)
如何发挥所有这些作用?为什么在dg.wait()
做同样的事情时还要有一个通知方法?
我觉得我对 GCD 的理解不是万无一失的,所以我想建立一些信心。有什么可以批评的也请批评指正。非常感谢您的帮助。
1) 不,调度组是隐式捕获的。您甚至不需要在 async
中捕获 self
,因为 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)
}
}
}
}