带DispatchGroup的Swift线程

时间:2019-02-05 22:29:26

标签: swift grand-central-dispatch

我有以下代码,当完成这样的任务时,它使用DispatchGroup来获得通知:

func getSomething(completion: ()->()) {
    completion()
}

func doSomeWork(completion: ()->()) {
    let myGroup: DispatchGroup = DispatchGroup()
    for _ in 0..<10 {
        myGroup.enter()
        getSomething {
            myGroup.leave()
        }
    }
    myGroup.notify(queue: DispatchQueue.main) { // this here is the key
        completion()
    }
}

DispatchQueue.global().async {
    print("We are doing background work")
    doSomeWork {
        print("We are done with the work - but on main thread now!!!")
    }
}

所以我的问题是我在线程上调用了某个函数,该函数具有在某个固定队列上调用的完成。

我的选择是:

  1. 检测Thread.isMainThread并在主队列或后台队列上通知
  2. 将我们正在处理的队列传递给所有函数调用 问题:这不是真正的智能设计模式
  3. 处理此完成具有固定队列的事实,然后再次手动调度

但是我对任何选择都不满意……我宁愿没有那么多的派遣。

想象一下:

DispatchQueue.global().async {
    print("We are doing background work")
    doSomeWork {
        DispatchQueue.global().async {
            print("Now we are in background again")
        }
    }
}

那已经是3级闭包了,使用起来并不好,尤其是在后台异步调用中我们有另一个闭包或级别的情况下。

在这里做什么的任何帮助都是很棒的!谢谢

1 个答案:

答案 0 :(得分:0)

  

问题是我要在一个函数上调用函数bla({// block code})   后台队列。 bla()在主体上调用完成处理程序   但是,由于调度组– JanoschHübner

再次检查您的代码段

func doSomeWork(completion: ()->()) {
    let myGroup: DispatchGroup = DispatchGroup()
    for _ in 0..<10 {
        myGroup.enter()
        getSomething {
            myGroup.leave()
        }
    }
    myGroup.notify(queue: DispatchQueue.main) { // this here is the key
        completion()
    }
}

然后看到,因为getSomething是同步的,所以您可以简单地编写

func doSomeWork(completion: ()->()) {
    //let myGroup: DispatchGroup = DispatchGroup()
    for _ in 0..<10 {
        //myGroup.enter()
        getSomething {
            //myGroup.leave()
        }
    }
    //myGroup.notify(queue: DispatchQueue.main) { // this here is the key
        completion()
    //}
}

如果getSomething应该是异步的,请使用适当的API在某些组中运行它

func doSomeWork(completion: ()->()) {
    let myGroup: DispatchGroup = DispatchGroup()
    let queue = DispatchQueue.global()
    for _ in 0..<10 {
        //myGroup.enter()
        queue.async(group: myGroup) {
            getSomething {
            //myGroup.leave()
            }
        }
    }
    myGroup.notify(queue: DispatchQueue.main) { // this here is the key
        completion()
    }
}

completion()的同一线程上运行doSomeWork(completion: ()->())很简单。

func doSomeWork(completion: ()->()) {
    let myGroup: DispatchGroup = DispatchGroup()
    let queue = DispatchQueue.global()
    for _ in 0..<10 {
        //myGroup.enter()
        queue.async(group: myGroup) {
            getSomething {
            //myGroup.leave()
            }
        }
    }
    //myGroup.notify(queue: DispatchQueue.main) { // this here is the key
        myGroup.wait()
        completion()
    //}
}

检查下一个操场页面,并查看DispatchQueue.concurrentPerform如何更改您的设计以及goup通知的工作方式

import PlaygroundSupport
import Dispatch

PlaygroundPage.current.needsIndefiniteExecution = true

let q0 = DispatchQueue.global()
let q1 = DispatchQueue(label: "my_queue", attributes: .concurrent)
let g = DispatchGroup()
let g1 = DispatchGroup()
q0.async(group: g) {
    print("1    message from \(q0): will do some concurrent jobs in the background")
    DispatchQueue.concurrentPerform(iterations: 5, execute: { (i) in
        sleep(1)
        print("\t",i)
    })
    print("2    message from \(q0): all concurrent jobs done")
    q0.async(group: g) {
        print("3    some other long time running on group...")
        sleep(3)
        print("3 ex")
    }
    q0.async(group: g1) {
        print("?    some other long time running on gifferent group...")
        sleep(4)
        print("? ex")
    }
    g1.notify(queue: .main, execute: {
        print("g1 empty")
    })
}
print("4    continue on main")
g.notify(queue: q1) {
    print("5    message from \(q1): finished a")
    DispatchQueue.main.async {
        sleep(1)
        print("6    from main, should stop playground execution?")
        //PlaygroundPage.current.finishExecution()
    }
    print("7    message from \(q1): finished b")

}
g1.notify(queue: .main) {
    print("8    from main, g1 is empty.")

}
print(" ... continue")

可在我的环境中打印

1    message from <OS_dispatch_queue_global: com.apple.root.default-qos>: will do some concurrent jobs in the background
4    continue on main
 ... continue
8    from main, g1 is empty.
     0
     2
     1
     3
     4
2    message from <OS_dispatch_queue_global: com.apple.root.default-qos>: all concurrent jobs done
3    some other long time running on group...
?    some other long time running on gifferent group...
3 ex
5    message from <OS_dispatch_queue_concurrent: my_queue>: finished a
7    message from <OS_dispatch_queue_concurrent: my_queue>: finished b
6    from main, should stop playground execution?
? ex
g1 empty