使用GCD,DispatchGroup如何在组离开之前(或之后)让项目从后台队列在主队列上运行,而不会出现死锁



给定某个类Foo在后台线程上调用Bar来执行一些工作,那么在封闭函数返回所需返回的值之前,Bar如何在不导致死锁的情况下设置要在主线程上完成的一些工作?

例如;asdf";"打印之前";完成";打印,然后从下面的示例中的func done() -> Bool返回true

import Dispatch
class Foo {
/// always called from the main queue
func done() -> Bool {
let group = DispatchGroup()
group.enter()
DispatchQueue.global().async {
Bar().perform {
DispatchQueue.main.async { print("asdf") } 
// "asdf" prints after "done" is printed
group.leave()
}
}
group.wait()
print("done")
return true
}
}

其中Bar简单地为:

struct Bar {
func perform(_ work: @escaping () -> Void) { work() }
}

我需要Bar能够在done()返回之前设置一些应该在主队列上执行的工作,而不会导致死锁(如果我们将上面的perform块更改为使用DispatchQueue.main.sync,就会发生这种情况,并且(假设done()总是在主线程上调用,事实就是这样(。

我唯一能想到的打印";asdf";在我们打印";完成";是将done()功能更改如下:

func done() -> Bool {
let group1 = DispatchGroup()
var completion: (() -> Void)? = nil
group1.enter()
DispatchQueue.global().async(group: group1) {
Bar().perform {
completion = { print("asdf") }
group1.leave()
}
}
group1.wait()
completion?()
print("done")
return true
}

这里completion块在函数返回之前在主线程上运行。然而,这感觉很笨拙。。。似乎是GCD应该为我们处理的事情。但我尝试过的其他一切都会在函数返回后运行。

想法?

GCD下的主队列不是可重入的,除非阻塞主线程,否则不能阻止done立即返回,也不能(因此(在第一个异步方法之后从done返回值。

所以,正如你在评论中所说的,你想做的是不可能的。

您可以从Bar完成处理程序内部的调用回主线程,例如通过另一个完成处理程序;但你不能";等待";

例如:

struct Bar {
func perform(_ work: @escaping () -> Void) {
print("work")
work()
}
}
class Foo {
func done(_ f: @escaping (Bool) -> ()) {
DispatchQueue.global().async {
Bar().perform {
DispatchQueue.main.async {
// adjust the order of these two lines as desired
print("asdf")
f(true)
}
}
}
}
}
let f = Foo()
f.done { what in
print(what)
print("done")
}

输出:

work
asdf
true
done

也许这对你有用:

struct Bar {
func perform(work: @escaping () -> Void, completion: @escaping () -> Void) {
onBackGround(work) { 
DispatchQueue.main.async { 
print("asdf") 
completion()
}
}
}
func done() { 
print("done")
}
}

称之为:

bar = .. 
bar.perform(work) { 
self.done()
}

相关内容

  • 没有找到相关文章

最新更新