22

DispatchQueueのタスクが終了するまでコードを待機させるにはどうすればよいですか? CompletionHandlerなどが必要ですか?これを達成するためにスウィフト3で、私はXcodeの8.2を使用して書いているタスクが完了するまで待つ

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 

} 

答えて

59

使用DispatchGroup秒。

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

またはあなたが待って(と返す)ことができます:あなたは、グループのenter()leave()呼び出しがバランスしているときに通知を受けることができますいずれか

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を設定する必要があります。

+0

別のクラスの関数を実行したいが、その関数を終了するのを待ってから、現在のクラスの中でどのように処理することができるのか? –

+1

@SaeedRahmatolahi: 'wait'アプローチを使用するか(ブロックするのが問題ない場合、つまりメインスレッドにない場合)、または補完ハンドラを提供するか、呼び出しクラスでnotifyアプローチを使用します。 – shallowThought

+0

非同期ブロックの外側で 'group.enter'をなぜ呼び出すのですか?グループに入ったり出たりするのは各ブロックの責任ではないでしょうか? – Bill

1

使用ディスパッチグループ

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

を使用する方法の例です。 – shallowThought

+0

@shallowThoughtだから本当です。 – Prateekro

+0

別のクラスの関数を実行したいが、その関数を終了するのを待ってから、現在のクラスの中でどのように処理できるのかを続けたい。 –

11

スウィフト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 
} 
関連する問題