gpt4 book ai didi

使用 DispatchGroup 进行 Swift 线程处理

转载 作者:行者123 更新时间:2023-11-30 10:50:57 25 4
gpt4 key购买 nike

我有以下代码,它使用 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 级闭包,并且不太好用,特别是如果在后台异步调用中我们有另一个闭包或级别。

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

最佳答案

The issue is that I‘m calling a function bla({ //block code }) on a background queue. bla() calls the completion handler on the main thread though, due to dispatch groups – Janosch Hü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()
//}
}

检查下一个 Playground 页面,看看 DispatchQueue.concurrentPerform 如何改变您的设计以及组通知如何工作

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

关于使用 DispatchGroup 进行 Swift 线程处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54544033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com