本文介绍了“块"主线程(dispatch_get_main_queue())和(或不)定期运行 currentRunLoop - 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

- (void)test_with_running_runLoop {
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    NSTimeInterval checkEveryInterval = 0.05;

    NSLog(@"Is main queue? : %d", dispatch_get_current_queue() == dispatch_get_main_queue());

    dispatch_async(dispatch_get_main_queue(), ^{
        sleep(1);
        NSLog(@"I will reach here, because currentRunLoop is run");
        dispatch_semaphore_signal(semaphore);
    });

    while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:checkEveryInterval]];

    NSLog(@"I will see this, after dispatch_semaphore_signal is called");
}

- (void)test_without_running_runLoop {
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    NSLog(@"Is main queue? : %d", dispatch_get_current_queue() == dispatch_get_main_queue());

    dispatch_async(dispatch_get_main_queue(), ^{
        sleep(1);
        NSLog(@"I will not reach here, because currentRunLoop is not run");
        dispatch_semaphore_signal(semaphore);
    });

    NSLog(@"I will just hang here...");
    while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW));

    NSLog(@"I will see this, after dispatch_semaphore_signal is called");
}

产生以下内容:

Starting CurrentTests/test_with_running_runLoop
2012-11-29 08:14:29.781 Tests[31139:1a603] Is main queue? : 1
2012-11-29 08:14:30.784 Tests[31139:1a603] I will reach here, because currentRunLoop is run
2012-11-29 08:14:30.791 Tests[31139:1a603] I will see this, after dispatch_semaphore_signal is called
OK (1.011s)

Starting CurrentTests/test_without_running_runLoop
2012-11-29 08:14:30.792 Tests[31139:1a603] Is main queue? : 1
2012-11-29 08:14:30.797 Tests[31139:1a603] I will just hang here...

我的问题彼此相关:

  1. 如果我理解正确的话,主队列(dispatch_get_main_queue())是一个串行队列.我用dispatch_semaphore_wait阻塞了主队列/主线程,那么为什么我在第一个测试用例中看到我会到达这里,因为currentRunLoop正在运行"(我对第二种情况没问题-以我的理解,它确实,它应该做什么)?

  1. If I understand it right, main queue (dispatch_get_main_queue()) is a serial queue. I block the main queue/main thread with dispatch_semaphore_wait, so why do I see the "I will reach here, because currentRunLoop is run" in the first test case (I'm OK with the second case - in my understanding, it does, what it should)?

串行队列如何在当前执行任务被阻塞的情况下,在当前任务解锁之前调度下一个任务(哦,这个神秘的 runLoop:beforeDate:)?

How a serial queue, having current executing task blocked, can have a next task (oh, this mysterious runLoop:beforeDate:) dispatched before the current one is unlocked?

我想听听详细全面对此的回答,因为非常非常多的事情(这里也是如此)取决于这个问题!

I want to hear detailed and comprehensive answer on this, because very, very much things (here around on SO too) depend on this issue!

更新:除了公认的答案,这个 SO 主题对这个问题有很好的答案:完成时调用主队列的异步队列单元测试模式

UPDATE: Besides the accepted answer, this SO topic has good answer to this question: Pattern for unit testing async queue that calls main queue on completion

推荐答案

因为主线程上的默认runloop有一个特殊的行为,当它运行时,它也为主调度队列处理.在这种情况下,您实际上并没有阻塞,因为您告诉 dispatch_semaphore_wait 立即超时,它正在这样做(返回非零,在您的 if 中计算为真)- 所以你运行你的while循环,你驱动当前的运行循环,因此你的排队块被执行.

Because the default runloop on the main thread has the special behaviour that, when run, it also processes for the main dispatch queue. You're not actually blocking in this case because you're telling dispatch_semaphore_wait to timeout immediately, which it's doing (returning non-zero, which evaluates in your if to true) - so you run through your while loop, where you drive the current run loop, and thus your enqueued block gets executed.

但我的回答很笼统,因为我不确定你对哪一部分感到惊讶.

But my answer is broad because I'm not sure what part you're surprised by.

这篇关于“块"主线程(dispatch_get_main_queue())和(或不)定期运行 currentRunLoop - 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-28 12:05
查看更多