是否可以在当前队列的末尾添加一个块,并确保在队列中的所有现有项目之后调用此块?
以下代码似乎不起作用:
- (void)someTaskWillBeDoneOnThisThreadLater {
// The current scope is a delegate method of a library I'm using,
// and unfortunately the required task gets executed after this delegate
// method is called.
// wait for current queue to be done with everything, including the current scope
dispatch_async(dispatch_get_current_queue(), ^{
// After everything is done, then call the main thread
dispatch_async(dispatch_get_main_queue(), ^{
// Perform some task on main thread
});
});
}
修改
以下代码修复了问题,但我真的不想依赖1秒的延迟。我宁愿找到更好的解决方案。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
sleep(1);
// Perform something on main thread
});
});
答案 0 :(得分:2)
我认为问题是你需要私人队列来完成这项工作。这段代码:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"FIRST");
dispatch_async(dispatch_get_current_queue(), ^{
NSLog(@"LAST");
dispatch_async(dispatch_get_main_queue(), ^{
// ...
});
});
sleep(2);
NSLog(@"SECOND");
});
给出:
2012-07-31 22:57:20.005 Objective-C App[22526:1703] FIRST
2012-07-31 22:57:20.009 Objective-C App[22526:2003] LAST
2012-07-31 22:57:22.010 Objective-C App[22526:1703] SECOND
这不是你想要的。即使dispatch_barrier_async
也无济于事。但是当你使用私人队列时:
dispatch_queue_t queue = dispatch_queue_create("test", 0);
dispatch_async(queue, ^{
NSLog(@"FIRST");
dispatch_async(queue, ^{
NSLog(@"LAST");
dispatch_async(dispatch_get_main_queue(), ^{
// ...
});
});
sleep(2);
NSLog(@"SECOND");
});
会给你想要的结果:
2012-07-31 23:04:41.882 Objective-C App[22564:1703] FIRST
2012-07-31 23:04:43.887 Objective-C App[22564:1703] SECOND
2012-07-31 23:04:43.889 Objective-C App[22564:1703] LAST
如您所见,“LAST”将在最后打印,它将等待2秒,直到已经在队列中的块完成。
答案 1 :(得分:0)
来自dispatch_barrier_async
文档:
...当障碍块到达私有并发的前面时 队列,它不会立即执行。相反,队列等待直到 它当前正在执行的块完成执行。那时, 屏障块自行执行。之后提交的任何块 屏障块完成后才会执行屏障块。
因此,在代码中用dispatch_async
替换dispatch_barrier_async
可以做你想做的事。
修改强>
这仅适用于私有(并发)队列,另请参阅@ Johnnywho的回答和以下注释。
我忽略了那部分文档,抱歉。
答案 2 :(得分:0)
虽然目前尚不清楚实际问题是否如您所述,但在GCD中有一个功能,从OS X 10.7或iOS 4.3开始实现此目的:dispatch_barrier_async()
。
使用此函数将块提交到队列会导致该块等待执行,直到所有先前的块都已完成;同样,所有后续的块都会等待屏障完成。
请注意,这仅与并发队列相关,因为串行队列的性质是它不会在所有先前提交的块完成之前开始执行任何阻止。