Bear with me, this will take some explanation. I have a function that looks like below.
Context: "aProject" is a Core Data object named LPProject with an array named "memberFiles" that contains instances of another Core Data object called LPFile. Each LPFile represents a file on disk, and we want to open each of these files and analyze its text by looking for @import instructions pointing to OTHER files. If we find the @import operators, we want to find the file that they point to, and then βlinkβ this file to this, adding a relation to the main data object that the first file represents. Since all this may take some time on large files, we will do this from the main stream using 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 } } }
Now where things get weird:
This code works, but I see a strange problem. If I run it on LPProject with several files (about 20), it works fine. However, if I run it on LPProject, which has more files (say 60-70), it correctly performs NOT . We never return to the main thread, NSLog(@"got to main thread"); never appears and the application freezes. BUT, (and this is where things get REALLY weird) --- if I run the code in a small FIRST project and THEN run it on a large project, everything works fine. This is ONLY when I first run the code in a large project that a problem arises.
And here is the kicker, if I change the second send line to this:
dispatch_async(dispatch_get_main_queue(), ^{
(That is, use async instead of sync to send the block to the main queue), everything works all the time. In excellence. Regardless of the number of files in the project!
I find it difficult to explain this behavior. Any help or advice on what to test next will be appreciated.
objective-c cocoa core-data objective-c-blocks grand-central-dispatch
Bryan Jun 30 '11 at 17:31 2011-06-30 17:31
source share