Dispatch_sync всегда планирует блок на главной теме

Я выполняю блок с использованием dispatch_sync, и блок выполняется правильно. Но этот блок выполняется на основном потоке. Согласно Apple Doc:

Последовательные очереди (также известные как частные очереди отправки) выполняют одну задачу в то время в том порядке, в котором они добавляются в очередь. The выполняемые в настоящее время задачи выполняются на отдельном потоке (который может меняться от задачи к задаче), которая управляется очередью отправки.

что означает (или то, что я понял), что текущий исполняемый процесс будет выполняться в отдельном потоке.

Ниже приведен код, который я использую, чтобы судить о том, что происходит. Он вызывается внутри NSURLConnection didReceiveData: метод делегирования (я знаю, что не должен делать это внутри метода didReceiveData: delegate, но это всего лишь образец для фокусировки на dispatch_sync). Ниже приведены различные способы, которые я могу принять в качестве доказательства моего заключения:

  • Использование dispatch_sync в Глобальной параллельной очереди

       dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            if ([NSThread isMainThread]) {
                NSLog(@"Main Thread");
            }
            else
                NSLog(@"Not on Main Thread");
    
            //Some Process
        });
    

Выход -

         Main Thread
         Main Thread 
         Main Thread
         // Main Thread printed till didReceiveData: gets called

  1. Использование dispatch_sync в собственной созданной очереди с помощью dispatch_queue_create

    // Create queue somewhere else like this
    dispatch_queue_t newQueue = dispatch_queue_create("WriteQueue", DISPATCH_QUEUE_SERIAL);
    
    
       dispatch_sync(newQueue, ^{
    
            if ([NSThread isMainThread]) {
                NSLog(@"Main Thread");
            }
            else
                NSLog(@"Not on Main Thread");
    
            //Some Process
        });
    

Выход -

         Main Thread
         Main Thread 
         Main Thread
         // Main Thread printed till didReceiveData: gets called

Я немного удивлен здесь, блок выполняется всегда в основном потоке, или я что-то упускаю. Думаю, что это похоже на Apple Doc. Кто-нибудь знает, что это такое?

Обновление. Как и в других дискуссиях, я понимаю, что dispatch_sync выполняет блок в одном и том же потоке (в большинстве случаев), то почему заявления apple docs в некоторых отношениях противоречат друг другу. Почему apple говорит: "Выполняемая в данный момент задача выполняется в отдельном потоке (который может варьироваться от задачи к задаче), который управляется очередью отправки". Или я все еще что-то пропустил?

Ответ 1

dispatch_sync() отправляет блок в тот же поток, что и в нормальном режиме.

ИЗМЕНИТЬ

Apple Documentation не только говорит об этом, но и говорит следующее:

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

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

Ответ 2

Для фона блока используйте

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // background code
});

Обратите внимание: _async, а не _sync

EDIT: аналогично, чтобы выполнить что-то в основном потоке, используйте

dispatch_async(dispatch_get_main_queue(), ^{
    // main thread code
});

Ответ 3

Важно понимать, что Grand Central Dispatch может гарантировать, что блок, отправленный в основную очередь, будет работать в основном потоке, но блок, отправленный в любую другую очередь, не имеет никаких гарантий относительно того, какой поток будет выполняться блок.

Никакой гарантии относительно того, на какой поток будет вызываться блок; однако гарантируется, что одновременно будет вызываться только один блок, отправленный в очередь отправки FIFO.

Grand Central Dispatch управляет пулом потоков и как можно больше использует существующие потоки. Если основной поток доступен для работы (т.е. В режиме ожидания), блок может быть выполнен в этом потоке.

Ответ 4

Вот как вы можете это сделать в Swift:

runThisInMainThread { () -> Void in
    // Runs in the main thread
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

Он включен как стандартная функция в моем репо, проверьте его: https://github.com/goktugyil/EZSwiftExtensions