For循环中的DispatchGroup

时间:2017-12-10 02:12:10

标签: swift asynchronous grand-central-dispatch

所以,我有一点时间试图让DispatchGroup在长时间的异步操作完成之前保持for循环迭代。我发现的大多数例子都非常简单明了,但我似乎无法按照我的预期让我的简单测试用例工作。

let group = DispatchGroup()

    for i in 1...3 {
        group.enter()
        print("INDEX \(i)")
        asynchronousOperation(index: i, completion: {
            print("HELLO \(i)")
            self.group.leave()

        })
        print("OUTSIDE \(i)")
    }


func asynchronousOperation(index: Int, completion: @escaping () -> ()) {
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+5) {
        print("DONE \(index)")
        completion()

    }
}

最终打印

START
INDEX 1
OUTSIDE 1
INDEX 2
OUTSIDE 2
INDEX 3
OUTSIDE 3
DONE 1
HELLO 1
DONE 2
HELLO 2
DONE 3
HELLO 3

我希望它能打印更像

的东西
START
INDEX 1
OUTSIDE 1
HELLO 1
INDEX 2
OUTSIDE 2
HELLO 2
INDEX 3
OUTSIDE 3
HELLO 3

只要在异步操作()内部调用group.leave()之后,OUTSIDE之后的下一个“INDEX”将不会被打印

可能是一些简单的我误解了 - 任何想法?

2 个答案:

答案 0 :(得分:2)

执行以下代码以获得正确的输出:

for i in 1...3 {
    let semaphore = DispatchSemaphore(value: 0) // create a semaphore with a value 0. signal() will make the value 1.
    print("INDEX \(i)")
    asynchronousOperation(index: i, completion: {
        print("HELLO \(i)")
        semaphore.signal() // once you make the signal(), then only next loop will get executed.
    })
    print("OUTSIDE \(i)")
    semaphore.wait() // asking the semaphore to wait, till it gets the signal.
}

   func asynchronousOperation(index: Int, completion: @escaping () -> ()) {
    DispatchQueue.global().asyncAfter(deadline: DispatchTime.now()+5) {
        print("DONE \(index)")
        completion()
    }
}

输出

INDEX 1 在外面1 完成1 你好1

INDEX 2 外面2 完成2 你好2

INDEX 3 外面3 完成3 你好3

答案 1 :(得分:1)

为了实现这一点,如果我理解正确,您可能想要使用DispatchSemaphore。这样做:

let semaphore = DispatchSemaphore(value: 1)

for i in 1...3 {
   self.semaphore.wait()
   print("INDEX \(i)")
   asynchronousOperation(index: i, completion: {
     print("HELLO \(i)")
     self.semaphore.signal()
   })
   print("OUTSIDE \(i)")
}


func asynchronousOperation(index: Int, completion: @escaping () -> ()) {
  DispatchQueue.global().asyncAfter(deadline: DispatchTime.now()+5) {
    print("DONE \(index)")
    completion()
  }
}