Objective c 阻止块运行,直到所有以前的队列项目都已完成
是否可以将块添加到当前队列的末尾,并确保在队列中所有现有项之后调用此块 下面的代码似乎不起作用:Objective c 阻止块运行,直到所有以前的队列项目都已完成,objective-c,grand-central-dispatch,Objective C,Grand Central Dispatch,是否可以将块添加到当前队列的末尾,并确保在队列中所有现有项之后调用此块 下面的代码似乎不起作用: - (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 //
- (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
});
});
从
dispatch\u barrier\u async
文档中:
。。。当屏障块到达专用并发服务器的前端时
队列,它不会立即执行。相反,队列将等待到
其当前执行的块将完成执行。在这一点上
屏障块自动执行。提交后提交的任何区块
在屏障块完成之前,不会执行屏障块
因此,将代码中的
dispatch\u async
替换为dispatch\u barrier\u async
应该可以满足您的需要
编辑:
这只适用于私有(并发)队列,请参见@Johnnywho的答案和以下注释
抱歉,我忽略了文档的这一部分。虽然不清楚实际问题是否如您所述,但GCD中有一个工具,可以从OS X 10.7或iOS 4.3开始实现这一点: 使用此函数向队列提交块会导致该块等待执行,直到所有先前的块都完成;同样,所有后续块都等待屏障完成
请注意,这仅与并发队列相关,因为串行队列的性质是,在所有以前提交的块完成之前,它不会开始执行任何块。我认为问题在于,您需要专用队列来完成此工作。此代码:
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\u barrier\u 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
如您所见,“最后一个”将在末尾打印,并将等待2秒钟,直到队列上已经存在的块完成。您所说的是哪种队列?这应该适用于串行队列,所以我猜您有一个并发队列?我真的不确定,我没有访问此框架的源代码。如果可以在没有2秒钟的情况下完成,这将是完美的delay@Johnnywho:现在我看到您的评论是正确的,“即使是分派\u barrier\u async也无济于事”。原因是
dispatch\u barrier\u async
只能用于私有并发队列,否则它的行为类似于dispatch\u async
。由于OP不知道在哪个队列上调用函数,因此这不会有多大帮助。@aryaxt delay不是此解决方案的一部分!sleep(2)仅模拟长任务来显示,该块将等待2秒以完成上一个任务queue@MartinR我再次复习了这个问题,我同意你们的看法。此方法可能不是从专用队列调用的,因此我的建议可能不起作用。dispatch\u barrier不起作用,因此我猜该队列是一个并发队列。dispatch\u barrier\u async
起作用,但仅适用于使用dispatch\u queue\u create(“测试”,dispatch\u queue\u concurrent)
创建的专用并发队列。在全局队列上,它的行为类似于dispatch\u async
。我将编辑我的答案。