为什么这个dispatch_sync()调用冻结? [英] Why is this dispatch_sync() call freezing?
问题描述
我使用Kiwi测试框架来测试我的应用程序中的身份验证方法。在调用dispatch_sync时,测试冻结,如下所示:
I'm using the Kiwi testing framework to test an authentication method in my app. The test freezes at a call to dispatch_sync which looks like this:
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_sync(main, ^
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];
});
我想知道为什么它冻结在那里,如果有人有任何提示。
I'd like to know why it freezes there, if anyone has any hints.
推荐答案
有关冻结提示的第二部分:
For the second part of your question regarding the hint on the freeze:
当在队列上调用 dispatch_sync
时,始终验证此队列是否不是当前队列( dispatch_get_current_queue code>)。因为
dispatch_sync
会将您的块排队作为第一个参数传递的队列,然后将等待此块执行,然后继续。
When calling dispatch_sync
on a queue, always verify that this queue is not already the current queue (dispatch_get_current_queue()
). Because dispatch_sync
will queue your block on the queue passed as the first parameter, and then will wait for this block to be executed before continuing.
所以如果 dispatch_get_current_queue()
和队列在队列中是相同的,队列在你的情况下,主队列将阻塞调用dispatch_sync直到...主队列作为执行块,但它不能,因为队列被阻塞,和这里有一个美丽的死锁
So if the dispatch_get_current_queue()
and the queue on which you enqueue your block are the same, namely the main queue in your case, the main queue will block on the call to dispatch_sync until… the main queue as executed the block, but it can't, as the queue is blocked, and you have a beautiful deadlock here.
一个解决方案(直到iOS6):
One solution ( up until iOS6):
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_block_t block = ^
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];
};
if (dispatch_get_current_queue() == main)
block(); // execute the block directly, as main is already the current active queue
else
dispatch_sync(main, block); // ask the main queue, which is not the current queue, to execute the block, and wait for it to be executed before continuing
注意, dispatch_get_current_queue()
只能用于调试目的,在生产。事实上,自iOS6.1.3起, dispatch_get_current_queue
已被弃用。
Be careful, dispatch_get_current_queue()
is only to be used for debugging purposes and never in production. In fact, dispatch_get_current_queue
is deprecated since iOS6.1.3.
如果您处于主要队列的特定情况(仅与主线程相关联),您可以改为测试 [NSThread isMainThread]
(由@ meaning-matters建议)。
If you are in the specific case of the main queue (which is associated with the main thread only), you may instead test [NSThread isMainThread]
as suggested by @meaning-matters.
顺便说一句,你确定需要 dispatch_sync
吗?
我想稍后发送通知,避免阻塞,直到它被发送,在你的情况下是可以接受的,所以你也可以考虑使用 dispatch_async
使用 dispatch_sync
并需要队列比较条件),这将避免死锁问题。
By the way, are you sure you need to dispatch_sync
in your case?
I guess sending your notification a bit later, avoiding to block until it has been sent, is acceptable in your case, so you may also consider using dispatch_async
(instead of using dispatch_sync
and needing the queue comparison condition), which would avoid the deadlock issue too.
这篇关于为什么这个dispatch_sync()调用冻结?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!