为什么苹果弃用了dispatch_get_current_queue?

10

为什么苹果弃用了dispatch_get_current_queue?这个调用有哪些风险?


可能是What GCD queue, main or not, am I running on?的重复问题。 - lucianomarisi
这不是重复的 - 我正在尝试弄清楚苹果为什么要弃用这个调用。 - Boon
思考原因对技术人员深入了解更有好处。为什么要关闭它? - Forrest
这个函数被弃用的原因可以在相关的手册页面中找到。一些原因已经在答案中提到,但并不全面。请参阅https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dispatch_get_current_queue.3.html。 - CouchDeveloper
2个回答

16

dispatch_get_current_queue在第一次使用时就没有太多意义。原因如下:有少量的“根”队列(每个优先级一个,然后是主队列)。每个其他队列最终都会针对其中的一个根队列。这意味着,在一般情况下,“我正在运行的队列是什么?”这个问题并不是一个单一的答案。

例如,如果您有一个针对队列A的队列B,那么对于提交到队列B的块,A B 都是该问题的合理答案。此外,由于所有队列最终都会针对全局/根队列之一,可以认为“最好”的答案是“它最终执行的任何根队列”,但这对任何人来说都不是真正有用的,因为它不能显著区分任何东西。

根据我的经验,在大多数情况下,人们希望从dispatch_get_current_queue中得到的答案是:“我最初提交到的队列是哪个?”然而,根据定义,提交块的代码已经知道它提交到了哪个队列(因为它正在进行提交)。因此,如果您需要捕获该信息,您可以在入队时轻松地这样做;您不需要dispatch_get_current_queue来回答该问题。对于这些情况,dispatch_get_current_queue只是一种快捷方式,并且还是一个有缺陷的快捷方式(因为它会针对队列进行选择)。

另一个重要的情况是当您想知道自己是否在主队列中时。对于这种情况,-[NSThread isMainThread]已经足够/具有权威性,所以您也不需要dispatch_get_current_queue

另外一个回答者也指出,dispatch_get_current_queue 经常被误用来尝试使用GCD队列模拟递归锁。在基于队列的系统中可靠地实现递归锁是不可能的,因为“队列不是锁”。 我在另一个答案中详细谈到了这个特定情况。


1
谢谢 - 我有点搞不懂“针对队列A的队列B”这个概念。您说的队列针对另一个队列是什么意思? - Boon
1
请查看 dispatch_set_target_queue() 的文档。当您创建一个新的私有队列时,默认情况下它会将目标设置为默认优先级全局并发队列(即 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))。您可以使用 dispatch_set_target_queue() 更改其目标。这使您能够设置任意层次结构的队列。 - ipmcc
好的,每个队列都可以有一个目标队列,因此队列可以按树状排序,但是我处于哪个队列是叶节点这是一个合理的问题呢?! - János
如我在答案中所解释的,如果你只想知道“叶子”队列,那么通过将块提交到该叶子队列,该信息已经可用于你。即,在提交块之前,你可以在块的闭包中捕获队列的引用。我知道这很笨拙,但实际上,需要知道你正在执行的队列通常是一个“代码异味”。为什么不发布一个新问题,询问你实际上想要做什么呢? - ipmcc
@ipmcc - [NSThread isMainThread] 不足以确定当前队列是否为主队列。它可能不是。 - Marcin
1
你真好,提到这个神秘的东西,然后又没有为大家解释。在绝大多数情况下,它是足够且权威的。当你的应用程序的主循环使用dispatch_main()而不是正常的GUI框架时,它是不够的。实际上,你会使用dispatch_main()并仍然需要知道是否在主队列上的情况非常罕见。(前者通常是非GUI进程,后者通常是GUI应用程序,在其中某些事情必须在主线程上发生。) - ipmcc

2
可能是由于方法使用不当导致的。
以下是文档中的引用:
“仅建议用于调试和日志记录目的:代码不得对返回的队列进行任何假设,除非它是全局队列之一或代码本身创建的队列。如果该队列不是由dispatch_get_current_queue()返回的队列,则代码不得假定对队列的同步执行不会因死锁而安全。” NSImage 中的 setFlipped: 也面临着相同的情况 - 苹果已将其弃用,因为程序员们以“错误”的方式使用它们:
“图像的flipped属性被广泛误解,已经被弃用。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接