阻止块运行,直到所有以前的队列项目都完成为止



是否可以将一个块添加到当前队列的末尾,并确保在队列中所有现有项之后调用此块?

下面的代码似乎不起作用:

- (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_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秒,直到队列中已经存在的块完成。

虽然还不清楚实际问题是否如您所描述的那样,但GCD中有一个功能,可以从OS X 10.7或iOS 4.3开始实现:dispatch_barrier_async()

使用此功能将块提交到队列会导致该块等待执行,直到所有先前的块都已完成;同样地,所有随后的块等待屏障完成。

请注意,这仅与并发队列相关,因为串行队列的性质是,在之前提交的所有块都完成之前,它不会开始执行任何块。

来自dispatch_barrier_async文档:

当障碍块到达私有并发的前端时队列,它不会立即执行。相反,队列等待,直到其当前正在执行的块完成执行。在这一点上屏障块本身执行。在直到屏障块完成,才执行屏障块。

因此,在代码中用dispatch_barrier_async替换dispatch_async应该可以满足您的需要。

编辑:

这只适用于私人(并发)队列,另请参阅@Johnnywho的回答和以下评论。

对不起,我忽略了文件的那部分。

最新更新