Как указывает Иаков, хотя они могут казаться одинаковыми, они разные вещи. На самом деле, существует существенная разница в том, как они обрабатывают отправку действий в основной поток, если вы уже работаете в основном потоке.
Я столкнулся с этим недавно, когда у меня был общий метод, который иногда запускался из чего-то в главном потоке, иногда нет. Чтобы защитить определенные обновления пользовательского интерфейса, я использовал для них -performSelectorOnMainThread:
без проблем.
Когда я переключился на использование dispatch_sync
в основной очереди, приложение блокировалось всякий раз, когда этот метод запускался в основной очереди. Читая документацию по dispatch_sync
, мы видим:
Вызов этой функции и ориентация
текущая очередь приводит к тупику.
где для -performSelectorOnMainThread:
мы видим
ждать
Булево значение, которое указывает, является ли
текущий поток блокируется до
указанный селектор выполняется на
ресивер на основной ветке. Уточнить
ДА, чтобы заблокировать эту тему; иначе,
укажите НЕТ, чтобы этот метод возвращал
немедленно.
Если текущий поток также является основным
нить, и вы указываете ДА для этого
параметр, сообщение доставлено
и обработано немедленно.
Я все еще предпочитаю элегантность GCD, лучшую проверку во время компиляции и большую гибкость в отношении аргументов и т. Д., Поэтому я сделал эту маленькую вспомогательную функцию для предотвращения взаимных блокировок:
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
Обновление: В ответ на то, что Дейв Дрибин указал на раздел предостережений на dispatch_get_current_queue()
, я перешел на использование [NSThread isMainThread]
в приведенном выше коде.
Я тогда использую
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
для выполнения действий, которые мне нужно защитить в главном потоке, не беспокоясь о том, в каком потоке был выполнен оригинальный метод.