Блок 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
});