为什么这个dispatch_sync()调用冻结? [英] Why is this dispatch_sync() call freezing?

查看:217
本文介绍了为什么这个dispatch_sync()调用冻结?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆