web-dev-qa-db-ja.com

タスクが終了するまで待っています

DispatchQueueのタスクが終了するまでコードを待機させるにはどうすればよいですか。 CompletionHandlerか何かが必要ですか?

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

}

私はXcode 8.2を使用しており、Swift 3で書いています。

64

これを実現するにはDispatchGroupsを使用してください。グループのenter()leave()の呼び出しが均衡したときに通知を受けることができます。

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

または、待つ(そして戻る)こともできます。

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
}

group.wait()は現在のキュー(おそらくあなたの場合はメインキュー)をブロックするので、(上記のサンプルコードのように)別のキューでdispatch.asyncを実行する必要があります。 デッドロックを回避する

161
shallowThought

Swift 3では、DispatchQueueが1つのタスクを終了するときに完了ハンドラーは不要です。さらに、あなたはさまざまな方法であなたの目標を達成することができます

一つの方法はこれです。

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

ループが終了するまで待ちますが、この場合あなたのメールスレッドはブロックします。

これと同じことができます

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

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

        ////// do your remaining work
    }

最後に一つだけ。タスクがDispatchQueueを使用して完了したときにcompletionHandlerを使用したい場合は、DispatchWorkItemを使用できます。

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

派遣団を利用する

   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

これらの状況では非同期機能を使用できます。あなたがDispatchGroup()を使うとき、時々デッドロックが起こるかもしれません。

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