2014-09-24 4 views
3

Есть ли какая-то разница между ними, если dispatch_sync вызывается в 3-х различных очереди какdispatch_sync() всегда выполнять блок в главном потоке

1.

dispatch_sync(dispatch_get_main_queue(),^(void){ 
     NSLog(@"this execute in main thread") // via [NSThread isMainThread] 

    }); 

2.

dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(void){ 
    NSLog(@"this also execute in main thread") // via [NSThread isMainThread] 
} 

3.

dispatch_queue_t queue; 
queue = dispatch_queue_create("com.example.MyQueue", NULL); 
dispatch_sync(queue, ^(void){ 
    NSLog(@"this also execute in main thread") // via [NSThread isMainThread] 
} 

Всякий раз, когда я вызов dispatch_sync, блок, выполненный в основном потоке, не учитывая, в какой очереди он отправлен. Итак, почему эта функция принимает очередь в качестве аргумента, поскольку она не использует ее. Может кто-нибудь прояснить это?

+0

Откуда вы знаете, что это выполнено в основной теме? – Droppy

+0

[NSThread isMainThread] говорит, что это основной поток. – russell

ответ

9

dispatch_sync является блокирует работу. То есть, функция не вернется, пока работа, представленная в блоке, не будет завершена.

Когда отправляются на асинхронную очередь - как один из глобальных очередей или параллельной очереди ваших собственных решений - нет оснований делать ничего, кроме вызова блока на потоке, который называется dispatch_sync(). Даже в случае вызова блока в синхронной очереди dispatch_sync() будет ждать до завершения в любом случае так, внутри, он может также остановиться, пока остальная часть работы не будет выполнена в очереди, а затем не будет выполнять блок напрямую.

Как оказалось, передача данных из нити A в резьбу B является дорогостоящей. Если очередь находится в состоянии, где выполнение может произойти немедленно, то dispatch_sync быстро выполнит выполнение, просто вызвав блок в потоке, который был вызван dispatch_sync.

И, по определению, вам все равно. Вызывающий поток заблокирован - ничего не может сделать - до тех пор, пока не вернется dispatch_sync().

Итак, действительно, все это деталь реализации. GCD может свободно выполнять блоки по тем потокам, которые он считает наиболее подходящими.Так получилось, что не является контекстным переключателем часто является самым важным правилом определения этого.

5

См dispatch_sync документации, которая отмечает

В качестве оптимизации, эта функция вызывает блок в текущем потоке, когда это возможно.

Если вы отправляете что-то синхронно, так как поток должен дождаться отправки отправленного кода, во всяком случае, он будет часто запускать этот код в текущем потоке. Поэтому, если он отправляется синхронно с основного потока, он будет работать в основном потоке. Если он отправляется синхронно с фоновым потоком, он будет работать в этом фоновом потоке.

Как отмечено ipmcc, хорошо известным исключением является то, что фоновый поток отправляет что-то синхронно с основным потоком. Как источник libdispatch говорит:

Это предпочтительнее выполнять синхронные блоки на текущем потоке за счет локального потока побочных эффектов, сбор мусора и т.д. Тем не менее, блоки, представленные в основной поток должен быть запущен на основной поток.

+0

есть ли случай/пример, где эта функция вызывает блок в фоновом потоке, а не в основном потоке? – russell

+0

Да, я уверен, что есть. Но во многих тривиальных примерах, когда вы говорите: «Я хочу, чтобы текущий поток подождал, пока я делаю что-то еще в другом потоке», компилятор может умело завершить «зачем беспокоиться о создании другого потока, если первый поток будет сидеть там и ждать, так или иначе." – Rob

+0

Я нашел случай, когда эта функция вызывает блок в фоновом потоке. Если я вызову dispatch_sync() в фоновом потоке, он больше не вызывает блок в основном потоке. Итак, дело в том, из которого вызывается поток dispatch_sync, эта функция сначала пытается вызвать блок в потоке вызывающего (текущий поток), если это невозможно, то может создать новый поток. – russell

Смежные вопросы