Asynchronous actions do not complete in order

我的梦境 提交于 2019-12-12 05:33:19

问题


I have the following swift code to allow for mapping of a users contacts to the webserver, and then show in the tableview:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {


    dispatch_group_enter(self.dispatch_group)
    dispatch_group_async(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
         print("start 1")

        self.contacts = self.findContacts()

        dispatch_group_leave(self.dispatch_group)
        print("End 1")
    }

    dispatch_group_enter(self.dispatch_group)
    dispatch_group_async(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
        print("start 2")

        // Method to match contacts with Firebase db:
        self.mapContactsToPresentFriends(self.contacts, firebaseMainURL: self.firebaseMainURL, usersSyncID: "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de")

        dispatch_group_leave(self.dispatch_group)
        print("End 2")
    }


    dispatch_group_notify(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {
        print("start 3")

        // Final load of who is left of conacts (not user or friend)
        for contact in self.contacts {

            let phoneNumber = contact.phoneNumbers[0].value as! CNPhoneNumber

            self.friends.append(Friend(userName: "", phoneNumber: phoneNumber.stringValue, status: 0, name: contact.givenName, userID: ""))
        }

        for friend in self.friends {
            print(friend.status)
        }

        self.tableView!.reloadData()

    })
}

However, noting the print("Start 1"), print("Start 2") and print("Start 3") statements, the log displays the execution as:

start 2
start 1
End 2
End 1
start 3

Which yields an inaccurate result. I need these asynchronous tasks to occur in order (as indicated by the print statements), or else the result will not make sense.

How can this be rearranged to ensure that it works?


回答1:


You should probably create a serial queue (use the dispatch_queue_create function with the DISPATCH_QUEUE_SERIAL attribute.)

Then submit your tasks to the serial queue. They will still run concurrently with the main thread, but each task in a serial queue completes before the next one starts.

You could also set up barriers at each point where you wanted the previous task to complete before beginning the next, but it sounds like you want ALL of your tasks to run sequentially so a serial queue is a better fit and easier to set up.




回答2:


If you really want these things to happen in order, there's no need for separate blocks.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
    print("start 1")
    let contacts = self.findContacts()
    print("End 1")

    print("start 2")
    // Method to match contacts with Firebase db:
    self.mapContactsToPresentFriends(contacts, firebaseMainURL: self.firebaseMainURL, usersSyncID: "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de")
    print("End 2")

    print("start 3")
    // Final load of who is left of conacts (not user or friend)
    var friends: [Friend] = []
    for contact in contacts {

        let phoneNumber = contact.phoneNumbers[0].value as! CNPhoneNumber

        friends.append(Friend(userName: "", phoneNumber: phoneNumber.stringValue, status: 0, name: contact.givenName, userID: ""))
    }

    for friend in friends {
        print(friend.status)
    }

    dispatch_async(dispatch_get_main_queue()) {
        // Any data/UI updates MUST be on the main queue
        self.friends = friends
        self.tableView!.reloadData()
    }
}

Another couple things to note:

  • Using dispatch_group_async replaces the need for _enter() and _leave(). You don't need both. (If you had really wanted to use groups, you'd also need dispatch_group_notify to complete the work.)
  • When you were dispatching each block separately, there's no need for an outer dispatch (since calling _async() is fast).
  • self.tableView.reloadData() (and UI updates) must happen on the main thread, and consequentially, your data source (e.g. self.friends) must also be updated on the main thread. I've changed this in the snippet above.


来源:https://stackoverflow.com/questions/37150319/asynchronous-actions-do-not-complete-in-order

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!