我曾经有一个帮助方法(静态),确保在正确的队列上调用完成块。
+ (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);
}
});}
是否有更好的方法可以在不进入主队列的情况下获得相同的行为?
答案 0 :(得分:3)
问题(以及不推荐使用get_current_queue的原因)是可以有许多当前队列。如果你将dispatch_sync从一个队列调度到另一个队列,那么两者现在都是“当前的”,因为dispatch_sync对其中任何一个都会死锁。与dispatch_set_target_queue相同。
避免死锁的可靠方法是始终使用dispatch_async(或其他异步API;例如dispatch_group_notify),以避免重入控制流,或传递足够的其他信息以正确决定(如果使用队列作为锁定,则可能有一个“已经锁定”的标志,例如你传递的。)
通常,需要递归锁定的代码或模拟它们的东西(比如使用当前队列决定是否调度dispync)是可能有一些不变量(锁定保护的那个)被破坏的代码,并且预计无论如何都会工作,这是一个有点可怕的概念。