[英]Waiting until the task finishes
如何让我的代码等到 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
}
使用DispatchGroup
来实现这一点。 您可以在组的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() {
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()
print(a) // you could also `return a` here
}
注意: group.wait()
阻塞当前队列(在您的情况下可能是主队列),因此您必须在另一个队列(如上面的示例代码中)上dispatch.async
以避免死锁。
在 Swift 3 中,当DispatchQueue
完成一项任务时不需要完成处理程序。 此外,您可以通过不同的方式实现您的目标
一种方法是这样的:
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
}
Swift 5 版本的解决方案
func myCriticalFunction() {
var value1: String?
var value2: String?
let group = DispatchGroup()
group.enter()
//async operation 1
DispatchQueue.global(qos: .default).async {
// Network calls or some other async task
value1 = //out of async task
group.leave()
}
group.enter()
//async operation 2
DispatchQueue.global(qos: .default).async {
// Network calls or some other async task
value2 = //out of async task
group.leave()
}
group.wait()
print("Value1 \(value1) , Value2 \(value2)")
}
使用调度组
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.
斯威夫特 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!)
}
}
}
不知何故,上面的 dispatchGroup enter() 和 leave() 命令不适用于我的情况。
不过,在后台线程的 while 循环中使用 sleep(5) 对我有用。 离开这里以防它帮助其他人并且它没有干扰我的其他线程。
在 Swift 5.5+ 中,您可以利用 Swift Concurrency,它允许从分派到主线程的闭包中返回一个值
func myFunction() async {
var a : Int?
a = await MainActor.run {
let b = 3
return b
}
print(a)
}
Task {
await myFunction()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.