我正在使用Kiwi测试框架在我的应用中测试身份验证方法。在调用dispatch_sync时,测试冻结,如下所示:
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_sync(main, ^
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationAuthenticationSuccess object:nil userInfo:ret];
});
我想知道为什么它会冻结,如果有人有任何提示。
答案 0 :(得分:54)
关于冻结暗示的问题的第二部分:
在队列上调用dispatch_sync
时,始终验证此队列不是当前队列(dispatch_get_current_queue()
)。因为 dispatch_sync
会将您的块排在作为第一个参数传递的队列上,然后将等待此块执行,然后再继续。
因此,如果dispatch_get_current_queue()
和你的块排队的队列是相同的,即你的主队列,主队列将阻塞对dispatch_sync的调用,直到......主队列执行为阻止,但它不能,因为队列被阻止,,你有一个漂亮的僵局。
一种解决方案([编辑]直到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
已被弃用。
如果您处于主队列的特定情况(仅与主线程相关联),您可以改为按照@ meaning-matters的建议测试[NSThread isMainThread]
。
顺便问一下,您确定需要dispatch_sync
吗?
我想稍后发送你的通知,避免在发送之前阻止,在你的情况下是可以接受的,所以你也可以考虑使用dispatch_async
(而不是使用dispatch_sync
并且需要队列比较条件),这也可以避免死锁问题。
答案 1 :(得分:39)
dispatch_get_current_queue()
,而在iOS 6.1.3上的主线程上发现dispatch_get_current_queue() == dispatch_get_main_queue()
为false
。
在iOS 6及更高版本中,只需执行以下操作:
dispatch_block_t block = ^
{
<your code here>
};
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}