如何在不使用dispatch_get_current_queue()的情况下验证我是否在给定的GCD队列上运行?

Bra*_*son 39 macos grand-central-dispatch ios objective-c-blocks

最近,我需要一个可用于保证在特定串行调度队列上同步执行给定块的函数.有可能从已经在该队列上运行的东西调用这个共享函数,所以我需要检查这种情况,以防止从同步调度到同一队列的死锁.

我使用如下代码来执行此操作:

void runSynchronouslyOnVideoProcessingQueue(void (^block)(void))
{
    dispatch_queue_t videoProcessingQueue = [GPUImageOpenGLESContext sharedOpenGLESQueue];

    if (dispatch_get_current_queue() == videoProcessingQueue)
    {
        block();
    }
    else
    {
        dispatch_sync(videoProcessingQueue, block);
    }
}
Run Code Online (Sandbox Code Playgroud)

此函数依赖于使用此函数dispatch_get_current_queue()来确定此函数正在运行的队列的标识,并将其与目标队列进行比较.如果匹配,它知道只运行块内联而不调度到该队列,因为该函数已在其上运行.

我听说过是否适当使用dispatch_get_current_queue()这样的比较是有争议的,我在标题中看到了这个措辞:

建议仅用于调试和记录目的:

代码不得对返回的队列做任何假设,除非它是全局队列之一或代码本身创建的队列.如果该队列不是dispatch_get_current_queue()返回的队列,则代码不得假设同步执行到队列是安全的死锁.

此外,在iOS 6.0中(但尚未针对Mountain Lion),GCD标题现在将此功能标记为已弃用.

听起来我不应该以这种方式使用这个功能,但我不确定我应该在它的位置使用什么.对于像上面那样针对主队列的函数,我可以使用[NSThread isMainThread],但是如何检查我是否在我的一个自定义串行队列上运行以便防止死锁?

Rob*_*ier 36

分配您想要使用的任何标识符dispatch_queue_set_specific().然后,您可以使用检查您的标识符dispatch_get_specific().

请记住,这dispatch_get_specific()很好,因为它将从当前队列开始,然后如果当前队列中没有设置密钥则向上走.这通常无关紧要,但在某些情况下可能有用.

  • 是的,这似乎是要走的路,并且在Apple开发者论坛上有趣的讨论支持:https://devforums.apple.com/message/710745#714753 (4认同)
  • @BradLarson FWIW,这与Core Data采用的方法相同.他们知道`performBlockAndWait`有完全相同的问题,对他们来说似乎已经足够了...... (2认同)