Runloop 不处理来自 dispatch_async 的事件

Posted

技术标签:

【中文标题】Runloop 不处理来自 dispatch_async 的事件【英文标题】:Runloop not processing events from dispatch_async 【发布时间】:2012-01-07 21:59:01 【问题描述】:

我在使用 dispatch_async 时遇到了一些问题。在我的应用程序主/UI 线程上,我在全局队列上调用 dispatch_async,并告诉它去执行一些具有完成处理程序的函数调用。我希望完成处理程序会被调用,但有时似乎不会。

dispatch_queue_t hiq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_async(hiq, ^(void)
            [object doSomethingAndThenCompletionHandler:^()
                //Do some stuff because I'm done
            ];
        );

有趣的是,每当我在文本字段中输入内容时,我都会这样做以响应 controlTextDidChange。 当我点击文本字段外时,所有完成处理程序都会立即触发。

我的猜测是,我所有的完成处理程序都在运行循环中的某个东西后面排队,然后当我的 UI 元素失去焦点时,就会释放队列。我不是运行循环方面的专家,无法知道我在文本字段或组合框中输入时到底发生了什么,但也许它正在占用运行循环?

编辑:我认为它与运行循环模式有关,因为当我打印出运行循环模式时,它会打印为 NULL,但在完成处理程序中打印为默认模式时除外。我正在使用组合框,并且仅当组合框打开并展开时才会出现问题。 UIScrollView blocks run loop? 我认为这可能与这个问题有关。大家觉得呢?

【问题讨论】:

您不必为了让dispatch_async 工作而使用运行循环。你在完成处理程序中做什么? 现在只是一些打印语句来测试它是否有效。我还注意到它似乎受到其他 UI 触发器的影响。如果我在文本字段中键入一个或两个字符,然后单击文本字段使其失去焦点,我的所有完成处理程序都会触发 我不想完成任何事情。没有它就行不通,所以我把它放进去看看是否可以让它工作。它真的只是为了实验 刚刚做了一个快速测试,我没有看到你描述的结果; controlTextDidChange:doSomethingAndThenCompletionHandler:(只是一个日志,然后是对处理程序的调用),处理程序本身都立即运行。没有看到doSomething... 几乎不可能帮助你 嗨乔希,我做了一些修改。只有在打开和展开组合框时才会发生这种情况 【参考方案1】:

当你做[[NSRunLoop currentRunLoop] runUntilDate:fiveSecondsFromNow]时,递归进入run loop,run loop正常处理事件。因此,如果文本字段收到另一个事件,它将再次调用您的方法。堆栈跟踪看起来像这样(有更多与 NSRunLoop 相关的帧):

main
NSApplicationMain
-[NSRunLoop runUntilDate:]
your method
-[NSRunLoop runUntilDate:]
your method

我不知道你为什么打电话给runUntilDate:,但这可能不是一个很好的理由。

如果您需要帮助了解为什么您的完成处理程序没有被调用,那么您需要向我们展示您的 doSomethingAndThenCompletionHandler: 方法的定义。

【讨论】:

我们还需要看doSomethingAndThenCompletionHandler:的定义。 看不到doSomethingAndThenCompletionHandler的实现:恐怕无法确定到底发生了什么…… 您需要向我们展示 一些 代码,我们可以使用这些代码重现问题并为您提供帮助。否则无法重现该问题,因为您的 doSomethingAndThenCompletionHandler: 代码中发生了导致此问题的某些事情。 在您的文本字段事件处理程序方法中放置一个断点。查看堆栈跟踪。如果看起来 NSRunLoop(或 CFRunLoop)是递归输入的,那么可能 NSTextField 以私有模式运行 runloop,不会耗尽包含完成处理程序的 GCD 调度队列。 我应该补充一点,我认为 NSTextField 不太可能做到我所描述的。【参考方案2】:

想通了我认为的问题。我正在使用的一些库很可能会发送 NSURLConnections 而不安排在常见的运行循环模式下运行。当组合框打开时,运行循环模式更改为事件跟踪模式,然后无法为它们获取回调。

【讨论】:

以上是关于Runloop 不处理来自 dispatch_async 的事件的主要内容,如果未能解决你的问题,请参考以下文章

RunLoop相关知识的总结

RunLoop总结:RunLoop基础知识

runloop

iOS核心笔记——RunLoop-基础

RunLoop的学习总结

RunLoop的学习总结