Waiting until the task finishes Waiting until the task finishes multithreading multithreading

Waiting until the task finishes


Use DispatchGroups to achieve this. You can either get notified when the group's enter() and leave() calls are balanced:

func myFunction() {    var a: Int?    let group = DispatchGroup()    group.enter()    DispatchQueue.main.async {        a = 1        group.leave()    }    // does not wait. But the code in notify() gets run     // after enter() and leave() calls are balanced    group.notify(queue: .main) {        print(a)    }}

or you can wait:

func myFunction() {    var a: Int?    let group = DispatchGroup()    group.enter()    // avoid deadlocks by not using .main queue here    DispatchQueue.global(attributes: .qosDefault).async {        a = 1        group.leave()    }    // wait ...    group.wait()    print(a) // you could also `return a` here}

Note: group.wait() blocks the current queue (probably the main queue in your case), so you have to dispatch.async on another queue (like in the above sample code) to avoid a deadlock.


In Swift 3, there is no need for completion handler when DispatchQueue finishes one task. Furthermore you can achieve your goal in different ways

One way is this:

    var a: Int?    let queue = DispatchQueue(label: "com.app.queue")    queue.sync {        for  i in 0..<10 {            print("Ⓜ️" , i)            a = i        }    }    print("After Queue \(a)")

It will wait until the loop finishes but in this case your main thread will block.

You can also do the same thing like this:

    let myGroup = DispatchGroup()    myGroup.enter()    //// Do your task    myGroup.leave() //// When your task completes     myGroup.notify(queue: DispatchQueue.main) {        ////// do your remaining work    }

One last thing: If you want to use completionHandler when your task completes using DispatchQueue, you can use DispatchWorkItem.

Here is an example how to use DispatchWorkItem:

let workItem = DispatchWorkItem {    // Do something}let queue = DispatchQueue.global()queue.async {    workItem.perform()}workItem.notify(queue: DispatchQueue.main) {    // Here you can notify you Main thread}


Swift 5 version of the solution

func myCriticalFunction() {    var value1: String?    var value2: String?    let group = DispatchGroup()    group.enter()    //async operation 1    DispatchQueue.global(qos: .default).async {         // Network calls or some other async task        value1 = //out of async task        group.leave()    }    group.enter()    //async operation 2    DispatchQueue.global(qos: .default).async {        // Network calls or some other async task        value2 = //out of async task        group.leave()    }        group.wait()    print("Value1 \(value1) , Value2 \(value2)") }