ios - 关闭和其他 GCD 问题中的 Weak DispatchGroup

标签 ios swift asynchronous grand-central-dispatch

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。

  1. 甚至有必要捕获我的调度组吗?
  2. 如果我不捕获它,我怎么知道我有一个保留周期?
  3. 如果调度组在其中一个回调执行期间消失了怎么办?它会因为等待而蒸发吗?
  4. 像这样经常实例化一个 DispatchQueue 是否不必要地昂贵(忽略 .userInteractive)?我之所以问这个特定问题,是因为在 Android 中启动线程非常昂贵(如此昂贵以至于 JetBrains 将大量资源用于 Kotlin 协程)。
  5. dg.notify(...) 如何发挥所有这些作用?为什么在 dg.wait() 做同样的事情时还要有一个通知方法?

我觉得我对 GCD 的理解不是万无一失的,所以我想建立一些信心。有什么可以批评的也请批评指正。非常感谢您的帮助。

最佳答案

1) 不,调度组是隐式捕获的。您甚至不需要在 async 中捕获 self,因为 GCD 闭包不会导致保留周期。

2) 没有保留周期。

3) 实际上,您是在滥用 DispatchGroup 来强制将异步任务变为同步。

4) 不,GCD 非常轻量级。

5) DispatchGroup 的主要目的是在所有异步任务(例如在重复循环中)完成时通知,而不考虑顺序。


更好的解决方案是嵌套异步任务。只需两项任务,厄运金字塔 是可控的。

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

关于ios - 关闭和其他 GCD 问题中的 Weak DispatchGroup,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57324405/

相关文章:

ios - 随机化 plist 的内容

ios - 更新 TableView 上的所有单元格而不使操作太 "heavy"内存

ios - Swift 4 didFinishPickingMediaWithInfo 保存图像

ios - 检测点击 UIButton 的特定部分

asynchronous - 在 Google Apps 脚本上运行异步函数

ios - 如何为单个图像设置多个选择选项?

ios - 使用后删除 AVAudioPlayerNode 导致崩溃

ios - 如何使用 Swift 选择图像的一部分、裁剪并保存?

c# - 任务列表中出现奇怪的空条目

c# - 是否有用于将控件绑定(bind)到异步数据的明确定义的模式?