正如雅各布所指出的,虽然它们可能看起来相同,但它们是不同的东西。事实上,如果您已经在主线程上运行,它们处理向主线程发送操作的方式存在显着差异。
我最近遇到了这个问题,我有一个通用方法,有时是从主线程上的某个东西运行的,有时不是。为了保护某些 UI 更新,我一直在毫无问题地使用-performSelectorOnMainThread:
它们。
当我切换到在主队列上使用dispatch_sync
时,只要在主队列上运行此方法,应用程序就会死锁。阅读关于 的文档dispatch_sync
,我们看到:
调用此函数并以当前队列为目标会导致死锁。
我们在哪里-performSelectorOnMainThread:
看到
等待
一个布尔值,指定当前线程是否阻塞,直到在主线程上的接收器上执行指定的选择器之后。指定 YES 来阻塞这个线程;否则,指定 NO 使该方法立即返回。
如果当前线程也是主线程,并且您为此参数指定 YES,则消息将立即传递和处理。
我仍然更喜欢 GCD 的优雅,它提供的更好的编译时检查,以及它在参数方面的更大灵活性等,所以我制作了这个小辅助函数来防止死锁:
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
更新:为了回应 Dave Dribin 指出的注意事项部分dispatch_get_current_queue()
,我已更改为[NSThread isMainThread]
在上面的代码中使用。
然后我用
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
执行我需要在主线程上保护的操作,而不用担心原始方法在哪个线程上执行。