核心数据在获取请求时冻结(死锁) [英] Core Data Freeze at fetch request ( Deadlock )

查看:269
本文介绍了核心数据在获取请求时冻结(死锁)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现抓取请求,但似乎处于死锁状态。

i'm trying to realize fetch request, but it seems to be in deadlock.

> 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

我有这种方法来使我的子上下文:

I have that methods to make my child context:

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, code> performBlock 。

My child context is NSPrivateQueueConcurrencyType and all saves is done using performBlock.

我想让这个运行正确吗?

What I suppose to do to make this run correctly?

谢谢。

推荐答案

您提及所有保存都使用 performBlock ,这是好的,但不够。 NSManagedObjectContext 几乎不是线程安全的一切。您的抓取请求不在 performBlock 的上下文中,但它确实需要。此外,您使用上下文的一切,以及当您使用您获取的托管对象。这样的死锁是线程问题的典型症状, performBlock 旨在帮助避免。

You mention that "all saves is done using performBlock", which is good but not enough. NSManagedObjectContext is not thread safe for pretty much everything. Your fetch request is not in the context of a performBlock, but it really needs to be. Also, everything else you use the context for, as well as when you use the managed objects that you fetch. Deadlocking like this is a classic symptom of threading issues, which performBlock was designed to help avoid.

这篇关于核心数据在获取请求时冻结(死锁)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆