Потерпите меня, это займет некоторое объяснение. У меня есть функция, которая выглядит так, как показано ниже.
Контекст: "aProject" - это объект Core Data с именем LPProject с массивом с именем "memberFiles", который содержит экземпляры другого объекта Core Data, называемого LPFile. Каждый LPFile представляет файл на диске, и мы хотим открыть каждый из этих файлов и проанализировать его текст, ища инструкции @import, указывающие на ДРУГИЕ файлы. Если мы находим операторы @import, мы хотим найти файл, на который они указывают, а затем "связать" этот файл с этим, добавив отношение к основному объекту данных, который представляет первый файл. Поскольку все это может занять некоторое время на больших файлах, мы сделаем это с основного потока, используя GCD.
- (void) establishImportLinksForFilesInProject:(LPProject *)aProject {
dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (LPFile *fileToCheck in aProject.memberFiles) {
if (//Some condition is met) {
dispatch_async(taskQ, ^{
// Here, we do the scanning for @import statements.
// When we find a valid one, we put the whole path to the imported file into an array called 'verifiedImports'.
// go back to the main thread and update the model (Core Data is not thread-safe.)
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"Got to main thread.");
for (NSString *import in verifiedImports) {
// Add the relationship to Core Data LPFile entity.
}
});//end block
});//end block
}
}
}
Теперь, где вещи становятся странными:
Этот код работает, но я вижу странную проблему. Если я запустил его на LPProject с несколькими файлами (около 20), он работает отлично. Однако, если я запустил его на LPProject, у которого больше файлов (скажем, 60-70), он корректно выполняет NOT. Мы никогда не возвращаемся к основному потоку, NSLog(@"got to main thread");
никогда не появляется и приложение зависает. НО, (и это то, где вещи становятся ДЕЙСТВИТЕЛЬНО странными) --- если я запускаю код в маленьком проекте FIRST и THEN запускаю его на большом проекте, все работает отлично. Это ТОЛЬКО, когда я сначала запускаю код в большом проекте, что проблема возникает.
И вот кикер, если я изменю вторую строку отправки на это:
dispatch_async(dispatch_get_main_queue(), ^{
(То есть, используйте async
вместо sync
для отправки блока в основную очередь), все работает все время. В совершенстве. Независимо от количества файлов в проекте!
Я затрудняюсь объяснить это поведение. Любая помощь или советы о том, что тестировать дальше, будут оценены.