我遇到了这样一个场景:我有一个委托回调,它可能发生在主线程或另一个线程上,直到运行时我才知道是哪个(使用StoreKit.framework).

我还需要在回调中更新UI代码,这需要在函数执行之前进行,所以我最初的 idea 是有这样一个函数:

-(void) someDelegateCallback:(id) sender
{
    dispatch_sync(dispatch_get_main_queue(), ^{
        // ui update code here
    });

    // code here that depends upon the UI getting updated
}

当它在后台线程上执行时,效果非常好.然而,当在主线程上执行时,程序会陷入死锁.

这一点对我来说似乎很有趣,如果我正确地阅读了dispatch_sync的文档,那么我希望它直接执行块,而不用担心将其调度到runloop中,如here所述:

作为一种优化,该函数在可能的情况下调用当前线程上的块.

但是,这没什么大不了的,它只是意味着更多的打字,这让我想到了这种方法:

-(void) someDelegateCallBack:(id) sender
{
    dispatch_block_t onMain = ^{
        // update UI code here
    };

    if (dispatch_get_current_queue() == dispatch_get_main_queue())
       onMain();
    else
       dispatch_sync(dispatch_get_main_queue(), onMain);
}

然而,这似乎有点倒退.这是GCD制作过程中的一个错误,还是我在文档中遗漏了什么?

推荐答案

我在the documentation (last chapter)年前发现了这个:

不要从正在执行的任务中调用dispatch_sync函数

此外,我遵循了您提供的链接,在dispatch_sync的描述中,我读到了以下内容:

调用此函数并以当前队列为目标会导致死锁.

所以我不认为这是GCD的问题,我认为唯一合理的方法是你发现问题后发明的方法.

Objective-c相关问答推荐

Objective c 判断文本字段是否为空

NSInternalInconsistencyException', reason: '试图将第 0 行插入第 0 节,但更新后第 0 节只有 0 行'

如何获取目标名称?

NSError 和 __autoreleasing

验证应用内购买的收据

当前时间是 HH:MM:SS am/pm 格式吗?

处理 ARC 中的指针对指针所有权问题

Objective C 代码是否有 github markdown 语言标识符?

ScrollView 手势识别器吃掉所有的事件

观察 UIDatePicker 的变化

.delegate=self 是什么意思?

UITextView 禁用文本 Select

判断一个 NSDate 是否大于另一个

了解按位与运算符

MKAnnotation 图像偏移与自定义引脚图像

ARC时代的财产与ivar

Objective-C构建中的重复符号错误?

ARC 下的 NSString 属性应该是强的还是复制的?

重复符号问题

如何将按钮放在不会在 iOS 中随表格滚动的 UITableView 上