如何让dispatch_after和dispatch_semaphore_t在GCD中一起工作?

时间:2012-09-07 02:57:01

标签: ios multithreading grand-central-dispatch

我对使用dispatch_afterdispatch_semaphore_t一起执行某些任务并在每个线程之间等待一段时间感到好奇。

我使用以下代码:

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

dispatch_after(time, queue, ^{

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    NSLog(@"blk01");

    dispatch_semaphore_signal(semaphore);

});

dispatch_after(time, queue, ^{

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    NSLog(@"blk02");

    dispatch_semaphore_signal(semaphore);

});

dispatch_after(time, queue, ^{

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    NSLog(@"blk03");

    dispatch_semaphore_signal(semaphore);

});

我在3秒后执行线程,而不是预期的延迟。

我做错了什么?有没有其他方法在dispatch_semaphore_t中执行线程,每个线程执行之间有延迟时间?

2 个答案:

答案 0 :(得分:4)

如果要串行(不同时)执行三个块,并且想要在块之间暂停,则比使用信号量更简单。最简单的方法是创建一个串行队列,并在每个块的开头或结尾放置sleep(或usleep):

dispatch_queue_t queue = dispatch_queue_create("my queue", 0);

dispatch_async(queue, ^{
    sleep(3);
    NSLog(@"blk01");
});

dispatch_async(queue, ^{
    sleep(3);
    NSLog(@"blk02");
});

dispatch_async(queue, ^{
    sleep(3);
    NSLog(@"blk03");
});

dispatch_release(queue);

sleep放入块中非常简单,但会占用一个线程。这可能无关紧要,除非你创造了很多队列并且在许多队列中睡觉。

如果您告诉我们您认为自己需要信号量的原因,或许我们可以为您提供更好的替代方案或建议如何正确使用它。

答案 1 :(得分:3)

您的代码不要求每次调用之间有3秒的延迟。它安排了3个块,全部在同一时间,所有3个块都采用信号量和日志。

您需要调整用于调度每个后续块的时间,或者您需要在之前的每个调用中安排后续dispatch_after()个呼叫。前者可能更简单,并且可以让您获得更精确的计时。如果你选择后者,请务必在每个区块中重新计算time,因为这是指绝对时间,而不是相对持续时间。