1

我曾经有一个辅助方法(静态),可确保在正确的队列上调用完成块。

  + (void)_deadlockCheckBlock:(void(^)(void))block caller:(dispatch_queue_t)caller {
     NSParameterAssert(block);
     NSParameterAssert(caller);
     if (caller == dispatch_get_current_queue()) {
        block();
     }
     else {
        dispatch_async(caller, block);
     }}

现在要克服的弃用

dispatch_get_current_queue()

我已经使用 get_main_queue 方法重写了该方法。

+ (void)_deadlockCheckBlock:(void(^)(void))block caller:(dispatch_queue_t)caller {
   NSParameterAssert(block);
   NSParameterAssert(caller);
   dispatch_sync(dispatch_get_main_queue(), ^{
     //This will ensure to be on the main queue
     if (caller == dispatch_get_main_queue()) {
        block();
     }
     else {
        dispatch_async(caller, block);
     }
   });}

有没有更好的方法可以在不进入主队列的情况下获得相同的行为?

4

1 回答 1

3

这样做的问题(以及不推荐使用 get_current_queue 的原因)是可能存在许多当前队列。如果您从一个队列 dispatch_sync 到另一个队列,那么两者现在都是“当前的”,因为 dispatch_sync 到它们中的任何一个都会死锁。与 dispatch_set_target_queue 相同。

避免死锁的可靠方法是始终使用dispatch_async(或其他异步API;例如dispatch_group_notify),以避免可重入控制流,或者传递足够的附加信息来正确决定(如果使用队列作为锁,你可以有一个例如,您传递的“已经锁定”标志)。

一般来说,需要递归锁或模拟它们的代码(例如使用当前队列来决定是否调度同步)是可能有一些不变量(锁正在保护的那个)被破坏并且预计无论如何都可以工作的代码,即一个有点可怕的概念。

于 2013-08-04T03:44:08.967 回答