2013-10-24 93 views
0

我試圖實現獲取請求,但它似乎處於死鎖狀態。核心數據凍結在獲取請求(死鎖)

> Thread 1, Queue : com.apple.main-thread 
> #0 0x38329fa8 in __psynch_mutexwait() 
> #1 0x38390f0e in _pthread_mutex_lock() 
> #2 0x2d3aaad0 in -[_PFLock lock]() 
> #3 0x2d3bbba4 in -[NSPersistentStoreCoordinator executeRequest:withContext:error:]() 
> #4 0x2d3ba7e6 in -[NSManagedObjectContext executeFetchRequest:error:]() 
> #5 0x2d448bb6 in -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:]() 
> #6 0x2d44932e in __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke() 
> #7 0x2d43ec82 in _perform() 
> #8 0x2d449030 in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]() 
> #9 0x2d3ba7e6 in -[NSManagedObjectContext executeFetchRequest:error:]() 
> #10 0x000e4c90 in +[PhotoDAO getNotSentPhotos:] at /Users/vitrinysolutions/Documents/Workspace XCode/Novo 
> SmileClick/SmileClick/SmileClick/DAOs/PhotoDAO.m:236 
> #11 0x0009f210 in -[EventManager loadQueue:] at /Users/vitrinysolutions/Documents/Workspace XCode/Novo 
> SmileClick/SmileClick/SmileClick/Util/EventManager.m:59 
> #12 0x00095fb0 in -[EventMainViewController viewDidAppear:] at /Users/vitrinysolutions/Documents/Workspace XCode/Novo 
> SmileClick/SmileClick/SmileClick/ViewControllers/EventMainViewController.m:60 
> #13 0x2fdf03da in -[UIViewController _setViewAppearState:isAnimating:]() 
> #14 0x2fdf085c in -[UIViewController _endAppearanceTransition:]() 
> #15 0x2fe9ced2 in -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:]() 
> #16 0x2ff6831c in __49-[UINavigationController _startCustomTransition:]_block_invoke() 
> #17 0x2feecc22 in -[_UIViewControllerTransitionContext completeTransition:]() 
> #18 0x2ffacff6 in __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke105() 
> #19 0x2fe0dfe8 in -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:]() 
> #20 0x2fe0dc36 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]() 
> #21 0x2fe0db4e in -[UIViewAnimationState animationDidStop:finished:]() 
> #22 0x2fa65d08 in CA::Layer::run_animation_callbacks(void*)() 
> #23 0x3824ed66 in _dispatch_client_callout() 
> #24 0x382557c0 in _dispatch_main_queue_callback_4CF$VARIANT$mp() 
> #25 0x2d62f820 in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__() 
> #26 0x2d62e0f4 in __CFRunLoopRun() 
> #27 0x2d598ce6 in CFRunLoopRunSpecific() 
> #28 0x2d598aca in CFRunLoopRunInMode() 
> #29 0x32286282 in GSEventRunModal() 
> #30 0x2fe3aa40 in UIApplicationMain() 
> #31 0x000aeedc in main at /Users/vitrinysolutions/Documents/Workspace XCode/Novo SmileClick/SmileClick/SmileClick/main.m:16 

我有一個方法,使我的孩子方面:

static __strong NSManagedObjectContext *context; 

+(NSManagedObjectContext*) context { 
    if (context == nil) { 
     context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     [context setParentContext: [((AppDelegate*)[[UIApplication sharedApplication] delegate]) managedObjectContext]]; 
    } 
    return context; 
} 

+ (void)save:(NSManagedObjectContext *)context { 
    [context performBlockAndWait:^{ 

     NSError *error; 

     if (![context save:&error]) { 

      NSLog(@"Child Context Error: %@", error); 

     } else { 
      NSManagedObjectContext *parentContext = [((AppDelegate*)[[UIApplication sharedApplication] delegate]) managedObjectContext]; 

      if (![parentContext save:&error]) { 
       NSLog(@"Parent Context Error: %@", error); 
      } 

     } 

    }]; 
} 

我的獲取方法:

+(NSArray *) getNotSentPhotos: (Event *) oEvent { 

    NSManagedObjectContext *context = [self context]; 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Photo" inManagedObjectContext:context]; 
    [fetchRequest setEntity:entity]; 

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(event == %@) AND (server_status == %@)", oEvent, SERVER_STATUS_PENDENTE]; 
    [fetchRequest setPredicate:predicate]; 

    NSError *error = nil; 
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; 

    return fetchedObjects; 

} 

我的孩子上下文是NSPrivateQueueConcurrencyType和保存所有使用performBlock完成。

我想要做什麼來使其正確運行?

謝謝。

回答

3

你提到「所有的保存都使用performBlock,這是很好,但還不夠。 NSManagedObjectContext幾乎不是線程安全的。您的提取請求不在performBlock的上下文中,但它確實需要。此外,您使用上下文的所有其他內容,以及您使用您獲取的託管對象的時間。像這樣的死鎖是線程問題的典型症狀,其中performBlock旨在幫助避免。

+0

謝謝,但我更新了我的代碼:[link](https://gist.github.com/iagocc/7157793),仍處於死鎖狀態。 下面的代碼有堆棧。 –

+0

這是一個獲取你使用上下文的唯一地方,或者你獲取的任何對象嗎?這看起來不太可能,因爲你沒有看它們就返回一個對象數組。僅僅將提取放入performBlock是不夠的。所有可能觸及上下文的內容都需要同步。 –

+0

我發現這個問題,我的NSFetchedResultsController沒有在performBlock中使用子上下文。 謝謝Tom Harrington。 –

0

我發現這個問題,我的NSFetchedResultsController沒有使用performBlock

謝謝Tom Harrington。

+2

如果你想感謝Tom Harrington,爲什麼不把他的答案標記爲正確,而不是你的? – hatfinch

+1

@hatfinch我的錯誤,謝謝。 –