0

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

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

- (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
                    });
                });
4

3 回答 3

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 秒,直到队列中的块完成。

于 2012-07-31T21:08:16.430 回答
0

dispatch_barrier_async文档中:

...当屏障块到达私有并发队列的前面时,它不会立即执行。相反,队列一直等到其当前正在执行的块完成执行。此时,屏障块自行执行。在屏障块完成之前,在屏障块之后提交的任何块都不会执行。

因此,在您的代码中替换dispatch_asyncbydispatch_barrier_async应该可以满足您的需求。

编辑:

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

我忽略了文档的那一部分,抱歉。

于 2012-07-31T20:59:59.177 回答
0

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

使用此函数将 Block 提交到队列会导致该 Block 等待执行,直到所有先前的 Block 都完成;同样,所有后续块等待屏障完成。

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

于 2012-07-31T21:01:11.590 回答