简体   繁体   English

dispatch group:for-loop中的for-loop *和* async调用

[英]dispatch group: for-loop *and* async calls within the for-loop

I understand how to use a dispatch group in a simple for-loop. 我理解如何在简单的for循环中使用调度组。 I, however, have a more complicated for-loop with more asynchronous calls within it. 但是,我有一个更复杂的for循环与更异步调用。 I want all the asynchronous calls to complete before executing the group completion code. 我希望在执行组完成代码之前完成所有异步调用。 I have tried to apply the principles in this answer to no avail- Can I use dispatch group not in a loop? 我试图在这个答案中应用原则无济于事 - 我可以使用不在循环中的调度组吗? . Here is my code, based off of the techniques I observed in that link: 这是我的代码,基于我在该链接中观察到的技术:

let group = DispatchGroup()

for ref in self.notifsRefList {
    group.enter()
    self.db.fetch(withRecordID: ref.recordID) { notifRecord, notifErr in
        print("async call")
        if notifErr == nil {

            // do stuff

            if let ref = notifRecord?.object(forKey: POST) as! CKReference? {
                group.enter()
                self.db.fetch(withRecordID: ref.recordID) { postRecord, err in
                    print("async call")
                    if err == nil {
                        // do stuff
                        group.leave()
                    }
                    else {
                        print("\(err)")
                        group.leave()
                    }
                }
            }
            if let ref = notifRecord?.object(forKey: USER_NOTIF) as! CKReference? {
                self.db.fetch(withRecordID: ref.recordID) { userRecord, err2 in
                    group.enter()
                    print("async call")
                    if err2 == nil {
                        // do stuff
                        group.leave()
                    }
                    else {
                        print("\(err2)")
                        group.leave()
                    }
                }
            }
            if let ref = notifRecord?.object(forKey: LIBRARY_ITEM) as! CKReference? {
                self.db.fetch(withRecordID: ref.recordID) { libRecord, err3 in
                    group.enter()
                    print("async call")
                    if err3 == nil {
                        // do stuff                        
                        group.leave()
                    }
                    else {
                        print("\(err3)")
                        group.leave()
                    }
                }
            }

            group.leave()

        }
        else {
            print("\(notifErr)")
            group.leave()
        }
    }

}


group.notify(queue: .main, execute: { // executed after all async calls in for loop finish
    print("done with all async calls")
    // do stuff
})

From the print statements I included, I know that my asynchronous calls are incorrect: sometimes "done with all async calls" prints before all instances of "async call." 从我包含的打印语句中,我知道我的异步调用是不正确的:有时“完成所有异步调用”在所有“异步调用”实例之前打印。 Any help in how to get this dispatch group working properly would be much appreciated. 如何让这个调度组正常工作的任何帮助将不胜感激。 Thanks! 谢谢!

The problem is the 2nd and 3rd inner async calls. 问题是第二次和第三次内部异步调用。 You are calling group.enter() inside the completion blocks instead of before the async calls. 您在完成块内而不是在异步调用之前调用group.enter()

There's also no need for so many calls to leave . 也没有必要leave这么多电话。

You need to move the two as follows: 你需要按如下方式移动两个:

let group = DispatchGroup()

for ref in self.notifsRefList {
    group.enter()
    self.db.fetch(withRecordID: ref.recordID) { notifRecord, notifErr in
        print("async call")
        if notifErr == nil {

            // do stuff

            if let ref = notifRecord?.object(forKey: POST) as! CKReference? {
                group.enter()
                self.db.fetch(withRecordID: ref.recordID) { postRecord, err in
                    print("async call")
                    if err == nil {
                        // do stuff
                    }
                    else {
                        print("\(err)")
                    }
                    group.leave()
                }
            }
            if let ref = notifRecord?.object(forKey: USER_NOTIF) as! CKReference? {
                group.enter()
                self.db.fetch(withRecordID: ref.recordID) { userRecord, err2 in
                    print("async call")
                    if err2 == nil {
                        // do stuff
                    }
                    else {
                        print("\(err2)")
                    }
                    group.leave()
                }
            }
            if let ref = notifRecord?.object(forKey: LIBRARY_ITEM) as! CKReference? {
                group.enter()
                self.db.fetch(withRecordID: ref.recordID) { libRecord, err3 in
                    print("async call")
                    if err3 == nil {
                        // do stuff                        
                    }
                    else {
                        print("\(err3)")
                    }
                    group.leave()
                }
            }
        }
        else {
            print("\(notifErr)")
        }
        group.leave()
    }
}

group.notify(queue: .main, execute: { // executed after all async calls in for loop finish
    print("done with all async calls")
    // do stuff
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM