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