我需要在主队列上同步分配一个区块.我不知道我当前是否在主线程上运行.简单的解决方案如下所示:

dispatch_sync(dispatch_get_main_queue(), block);

但是,如果我当前在主队列上运行的一个块中,这个调用会造成死锁.(同步调度等待块完成,但块甚至没有开始运行,因为我们正在等待当前块完成.)

显然,下一步是判断当前队列:

if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
    block();
} else {
    dispatch_sync(dispatch_get_main_queue(), block);
}

这很管用,但很难看.在我至少把它隐藏在一些自定义函数后面之前,这个问题难道没有更好的解决方案吗?我要强调的是,我负担不起异步调度块的费用——应用程序处于异步调度的块执行"太晚"的情况下.

推荐答案

我需要在Mac和iOS应用程序中定期使用类似的功能,因此我使用以下帮助器功能(最初在this answer中描述):

void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

你可以通过

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});

这就是你在上面描述的过程,我已经和其他几个开发人员谈过了,他们已经独立地为自己设计了类似的东西.

我用了[NSThread isMainThread]而不是dispatch_get_current_queue(),因为caveats section for that function曾经警告不要用它来进行身份测试和the call was deprecated in iOS 6.

Objective-c相关问答推荐

Objective-C NSMutableArray 在枚举时发生了变异?

如何使用第一个字符作为部分名称

Objective C 布尔数组

如何使用格式化占位符本地化字符串?

在@implementation 而不是@interface 定义的类变量?

检测到与加载的库不匹配的 UUID

UITextField 中的文本在编辑后向上移动(编辑时居中)

iOS框架改变一个属性(例如宽度)

UITextView 禁用文本 Select

Electron邮件镇静 iOS 8

'supportedInterfaceOrientations' 实现中的返回类型冲突: - 警告

ios 11 UITabBar UITabBarItem 定位问题

如何对包含数字的 NSMutable 数组进行排序?

UIWebView didFinishLoading 多次触发

如何在 Objective-C (iOS) 中判断 NaN 值

如何设置 NSPredicate 来查找具有 nil 属性的对象

如何本地化 iOS 故事板

Xcode - 如何将 XIB 连接到 ViewController 类

目标覆盖 FRAMEWORK_SEARCH_PATHS 构建设置

Objective C 消息分发机制