Блок dispatch_async в главной очереди никогда не будет execeuted

У меня есть приложение, которое использует очередь подключения, которая обрабатывает соединения в фоновом потоке. Каждое соединение отправляет сообщение JSON, а затем, когда оно получает успех, сохраняет некоторые объекты в coredata.

Как только все соединения завершены, я вызываю dispatch_async в основном потоке, чтобы вызвать метод finished.

Однако при очень специфических условиях передачи данных/сохранения я заметил, что блок dispatch_async для основного потока никогда не вызывается, а экран приложения зависает, все выполнение останавливается, и приложение сидит без дела с помощью замороженный экран. мощность обработки в соответствии с xcode равна 0%.

Вот метод с неудавшимся блоком.

- (void)connectionDidComplete
{
    _completeConnections++;

    _syncProgress = (float)_completeConnections / (float)_totalConnections;

    dispatch_async(mainQueue, ^(void) {
        [[NSNotificationCenter defaultCenter] postNotificationName:SyncQueueDidUpdateNotification object:nil];
    }); <-- this dispatch works

    if (_completeConnections == _totalConnections)
    {
        // clear unsynced data
        NSArray *syncedObjects = [SyncObject completedSyncObjects];

        if (syncedObjects.count > 0)
        {
            for (SyncObject *syncObject in syncedObjects)
            {
                [syncObject delete];
            }
        }

        //this method saves the current context, then merges this context with the main context right after
        [[VS_CoreDataManager sharedManager] saveManagedObjectContextAndWait:managedObjectContext];

        // cleanup the thread context
        [[VS_CoreDataManager sharedManager] unRegisterManagedObjectContextForThread:currentThread];
        managedObjectContext = nil;

        // complete sync
        dispatch_async(mainQueue, ^(void) {
            [self performSelector:@selector(finishSync) withObject:nil afterDelay:2];
        }); <-- this dispatch never gets called
    }
}

Мое подозрение в том, что эта проблема имеет какое-то отношение к сохранению контекста, а затем к его объединению. И, возможно, в то время как это происходит, его выпущенный в середине слияния, в результате чего некоторые странные зависают, и отправка не выполняется. Однако это только предположение, и я не знаю, как это исправить.

Любые идеи?

Спасибо.

Ответы

Ответ 1

Если блок в основном потоке не выполняется, это связано с 1 из 2 причин.

  • Основной поток заблокирован; вообще не обрабатывает никаких событий. Получил цикл while() в основном потоке? Это сделало бы это. Замок? Там вы идете.

  • Основной поток запускает цикл модального запуска внутри внешнего цикла цикла. Асинхронные отправки в основной цикл событий - основной поток - в этом случае не будут обрабатываться.

Установите точку останова на этом dispatch_async() и посмотрите, что делает основной поток (в момент отправки основной поток, скорее всего, уже находится в плохом состоянии).

Предложение DarkDust использования dispatch_after() является хорошим, но вряд ли будет работать в том смысле, что почти наверняка ваш основной поток не обрабатывает события, когда возникает проблема. То есть устраните проблему, затем перейдите к dispatch_after(), как предлагает DarkDust.

Ответ 2

Я считаю, что это отличная дискуссия. Я наткнулся на это, когда у меня был следующий код:

   dispatch_synch(dispatch_get_main_queue()){
        print("I am here")
   }

код печати не выполнялся, так как я отправлял блок "synch" в серийном основном потоке, который вызвал блокировку. печать ожидала завершения отправки, и отправка ожидала окончания печати. Когда вы отправляете в основной последовательной очереди, вы должны использовать dispatch_async. и я предполагаю, что если вы используете параллельную очередь, тогда лучше рассылать синхронизирующие игры

Ответ 3

Если ваш основной поток занят модальной runloop, вы можете попробовать

CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, block
    });