webentwicklung-frage-antwort-db.com.de

Warten, bis die Aufgabe abgeschlossen ist

Wie kann ich meinen Code warten lassen, bis die Aufgabe in DispatchQueue abgeschlossen ist? Benötigt es einen CompletionHandler oder so etwas?

func myFunction() {
    var a: Int?

    DispatchQueue.main.async {
        var b: Int = 3
        a = b
    }

    // wait until the task finishes, then print 

    print(a) // - this will contain nil, of course, because it
             // will execute before the code above

}

Ich verwende Xcode 8.2 und schreibe in Swift 3.

55

Verwenden Sie DispatchGroups, um dies zu erreichen. Sie können entweder benachrichtigt werden, wenn die Aufrufe der Gruppe enter() und leave() ausgeglichen sind:

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

oder du kannst warten (und zurückkehren):

func myFunction() -> Int? {
    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()

    // ... and return as soon as "a" has a value
    return a
}

Hinweis : group.wait() blockiert die aktuelle Warteschlange (in Ihrem Fall wahrscheinlich die Hauptwarteschlange). Sie müssen also .async in einer anderen Warteschlange (wie im obigen Beispielcode) ausführen, um ein Deadlockzu vermeiden.

146
shallowThought

In Swift 3 ist kein Abschluss-Handler erforderlich, wenn DispatchQueue eine Aufgabe abschließt. Außerdem können Sie Ihr Ziel auf verschiedene Weise erreichen

Ein Weg ist das.

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

Es wird warten, bis die Schleife beendet ist, aber in diesem Fall wird Ihr Mail-Thread blockiert.

Sie können dasselbe auch so machen 

    let myGroup = DispatchGroup()
    myGroup.enter()
    //// Do your task

    myGroup.leave() //// When your task completes
     myGroup.notify(queue: DispatchQueue.main) {

        ////// do your remaining work
    }

Eine letzte Sache. Wenn Sie completionHandler verwenden möchten, wenn Ihre Aufgabe mit DispatchQueue abgeschlossen ist, können Sie DispatchWorkItem verwenden.

Hier ist ein Beispiel, wie man DispatchWorkItem verwendet.

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
}
20
Usman Javed

Versandgruppe verwenden 

   dispatchGroup.enter()
   FirstOperation(completion: { _ in
dispatchGroup.leave()
  })
    dispatchGroup.enter()
    SecondOperation(completion: { _ in
dispatchGroup.leave()
  })
   dispatchGroup.wait() //Waits here on this thread until the two operations complete executing.
1
Sahil Arora

Swift 4

Sie können die Async-Funktion für diese Situationen verwenden. Wenn Sie DispatchGroup() verwenden, kann manchmal Deadlock vorkommen.

var a: Int?
@objc func myFunction(completion:@escaping (Bool) -> () ) {

    DispatchQueue.main.async {
        let b: Int = 3
        a = b
        completion(true)
    }

}

override func viewDidLoad() {
    super.viewDidLoad()

    myFunction { (status) in
        if status {
            print(self.a!)
        }
    }
}
0
codeByThey