executeFetchRequest 挂起并且从不返回错误或继续

Posted

技术标签:

【中文标题】executeFetchRequest 挂起并且从不返回错误或继续【英文标题】:executeFetchRequest hangs and never returns error or proceeds 【发布时间】:2013-08-31 03:46:57 【问题描述】:

我正在使用AppDelegate 的默认managedObjectContext,当我使用executeFetchRequest 时,它永远不会进入下一行或因错误而崩溃。这是在后台线程上,所以 UI 不会冻结,但数据永远不会填充——我的活动指示器永远不会停止,我的调试告诉我它永远不会脱离该语句。我遍历了每一行,并将其缩小到executeFetchRequest 方法。这可能是什么原因造成的?没有保存任何对象,但我认为这与它没有任何关系。到目前为止,已经一个小时了,所以很明显出了点问题。最后,这种情况只有 40% 的时间发生。

代码如下:

NSSortDescriptor *byTimestamp = [NSSortDescriptorWithKey:@"timestamp" ascending:NO];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Message"];
[fetchRequest setSortDescriptors:@[byTimestamp]];
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSArray *messages = [managedObjectContext executeFetchRequest:fetchRequest error:&error];//hangs on this line!!
if(error != nil)
  NSLog(@"Error: %@", [error localizedDescription]);

这是我的回溯:

* thread #1: tid = 0x1c03, 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10, stop reason = signal SIGSTOP
    frame #0: 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #1: 0x9329ccb0 libsystem_kernel.dylib`mach_msg + 68
    frame #2: 0x02488a49 CoreFoundation`__CFRunLoopServiceMachPort + 185
    frame #3: 0x0248d84b CoreFoundation`__CFRunLoopRun + 1243
    frame #4: 0x0248cf44 CoreFoundation`CFRunLoopRunSpecific + 276
    frame #5: 0x0248ce1b CoreFoundation`CFRunLoopRunInMode + 123
    frame #6: 0x029637e3 GraphicsServices`GSEventRunModal + 88
    frame #7: 0x02963668 GraphicsServices`GSEventRun + 104
    frame #8: 0x0041165c UIKit`UIApplicationMain + 1211
    frame #9: 0x000027ad qub`main(argc=1, argv=0xbffff418) + 141 at main.m:16

  thread #3: tid = 0x2203, 0x932a09ca libsystem_kernel.dylib`kevent64 + 10
    frame #0: 0x932a09ca libsystem_kernel.dylib`kevent64 + 10
    frame #1: 0x01c8cc2b libdispatch.dylib`_dispatch_mgr_invoke + 863
    frame #2: 0x01c8c8cc libdispatch.dylib`_dispatch_mgr_thread + 61

  thread #4: tid = 0x2303, 0x932a00ee libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x932a00ee libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x9017904c libsystem_c.dylib`_pthread_workq_return + 45
    frame #2: 0x90178e19 libsystem_c.dylib`_pthread_wqthread + 448

  thread #5: tid = 0x2403, 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #0: 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #1: 0x9329ccb0 libsystem_kernel.dylib`mach_msg + 68
    frame #2: 0x02488a49 CoreFoundation`__CFRunLoopServiceMachPort + 185
    frame #3: 0x0248d8d4 CoreFoundation`__CFRunLoopRun + 1380
    frame #4: 0x0248cf44 CoreFoundation`CFRunLoopRunSpecific + 276
    frame #5: 0x0248ce1b CoreFoundation`CFRunLoopRunInMode + 123
    frame #6: 0x055ad310 WebCore`RunWebThread(void*) + 608
    frame #7: 0x90176557 libsystem_c.dylib`_pthread_start + 344

  thread #8: tid = 0x2703, 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #0: 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #1: 0x9329ccb0 libsystem_kernel.dylib`mach_msg + 68
    frame #2: 0x02488a49 CoreFoundation`__CFRunLoopServiceMachPort + 185
    frame #3: 0x0248d8d4 CoreFoundation`__CFRunLoopRun + 1380
    frame #4: 0x0248cf44 CoreFoundation`CFRunLoopRunSpecific + 276
    frame #5: 0x0248ce1b CoreFoundation`CFRunLoopRunInMode + 123
    frame #6: 0x00ec7c7c Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 298
    frame #7: 0x00ec7b45 Foundation`-[NSRunLoop(NSRunLoop) run] + 82
    frame #8: 0x00085c60 qub`+[AFURLConnectionOperation networkRequestThreadEntryPoint:](self=0x000d2f1c, _cmd=0x000af418, object=0x00000000) + 304 at AFURLConnectionOperation.m:195
    frame #9: 0x00f150d5 Foundation`-[NSThread main] + 76
    frame #10: 0x00f15034 Foundation`__NSThread__main__ + 1304
    frame #11: 0x90176557 libsystem_c.dylib`_pthread_start + 344

  thread #9: tid = 0x2803, 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #0: 0x9329d7d2 libsystem_kernel.dylib`mach_msg_trap + 10
    frame #1: 0x9329ccb0 libsystem_kernel.dylib`mach_msg + 68
    frame #2: 0x02488a49 CoreFoundation`__CFRunLoopServiceMachPort + 185
    frame #3: 0x0248d8d4 CoreFoundation`__CFRunLoopRun + 1380
    frame #4: 0x0248cf44 CoreFoundation`CFRunLoopRunSpecific + 276
    frame #5: 0x0248ce1b CoreFoundation`CFRunLoopRunInMode + 123
    frame #6: 0x00fccebe Foundation`+[NSURLConnection(Loader) _resourceLoadLoop:] + 393
    frame #7: 0x00f150d5 Foundation`-[NSThread main] + 76
    frame #8: 0x00f15034 Foundation`__NSThread__main__ + 1304
    frame #9: 0x90176557 libsystem_c.dylib`_pthread_start + 344

  thread #10: tid = 0x2903, 0x9329fbe6 libsystem_kernel.dylib`select$DARWIN_EXTSN + 10
    frame #0: 0x9329fbe6 libsystem_kernel.dylib`select$DARWIN_EXTSN + 10
    frame #1: 0x024cacb7 CoreFoundation`__CFSocketManager + 1255
    frame #2: 0x90176557 libsystem_c.dylib`_pthread_start + 344

  thread #11: tid = 0x2a03, 0x9329f91a libsystem_kernel.dylib`__psynch_mutexwait + 10
    frame #0: 0x9329f91a libsystem_kernel.dylib`__psynch_mutexwait + 10
    frame #1: 0x9017c13b libsystem_c.dylib`pthread_mutex_lock + 595
    frame #2: 0x014cdb01 CoreData`-[_PFLock lock] + 33
    frame #3: 0x014cdada CoreData`-[NSPersistentStoreCoordinator lock] + 42
    frame #4: 0x014e257e CoreData`-[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1182
    frame #5: 0x014e09c9 CoreData`-[NSManagedObjectContext executeFetchRequest:error:] + 569
    frame #6: 0x000492fe qub`__36-[RIPConvosViewController pullData:]_block_invoke(.block_descriptor=0x118e9320, newMessages=0x00000000, oldMessages=0x00000000) + 638 at RIPConvosViewController.m:73
    frame #7: 0x00048fb4 qub`-[RIPConvosViewController pullData:](self=0x075293d0, _cmd=0x000abda7, completion=0xb0375ef0) + 212 at RIPConvosViewController.m:103
    frame #8: 0x0004bab8 qub`__40-[RIPConvosViewController refreshTable:]_block_invoke(.block_descriptor=0x118d2e50) + 168 at RIPConvosViewController.m:236
    frame #9: 0x01c8753f libdispatch.dylib`_dispatch_call_block_and_release + 15
    frame #10: 0x01c99014 libdispatch.dylib`_dispatch_client_callout + 14
    frame #11: 0x01c8a2e8 libdispatch.dylib`_dispatch_root_queue_drain + 335
    frame #12: 0x01c8a450 libdispatch.dylib`_dispatch_worker_thread2 + 39
    frame #13: 0x90178e12 libsystem_c.dylib`_pthread_wqthread + 441

顺便说一句,这段代码在 RIPConvosViewController 类的 pullData 方法中名为 fetchBlock 的块中。

我相信这是一个线程问题,但我不知道如何解决这个问题——我应该确保我对 Core Data 的所有调用都在同一个线程上吗?如果这是解决方案,我该怎么做?

【问题讨论】:

你在哪里设置你想要获取的实体? 刚刚修好了!哎呀!我的错字 当所有线程卡在executeFetchRequest: 时提供回溯。要获得回溯,请在调试器中按“暂停”,然后在 lldb 控制台中键入 bt all 检查线程 #11 的跟踪。看起来该代码应该在主线程上运行。 Core Data 发生死锁和锁定的最可能原因是当您在创建它的线程之外的线程上使用 NSManagedObject 时。当您将线程限制模型与 Core Data 一起使用时,这适用。 我的问题是我的获取需要一些时间并且它们冻结了 UI,所以我不想在主线程上调用它——我如何在另一个线程上执行此操作并且仍然避免这种情况什么样的情况? 【参考方案1】:

我遇到了同样的问题并检查了这个帖子:executeFetchRequest:error: freezes app

我通过将我的 NSManagedObjectContext 请求放在 @synchronized 块中解决了这个问题。

我的代码是:

-(void)saveBookmarksToCache:(NSMutableArray *) bookmarkList error:(NSError **)error


    NSFetchRequest *allBookmarks = [[NSFetchRequest alloc] init];
    [allBookmarks setEntity:self.bookmarkDescription];
    [allBookmarks setIncludesPropertyValues:NO]; // Just fetch the Id

    __autoreleasing NSError *reqError = nil;
    NSArray *bookmarks = [self.managedObjectContext executeFetchRequest:allBookmarks error:&reqError];


    if (reqError != nil)
        error = &reqError;
    ...

    // Save
    [self.managedObjectContext save:&reqError];
    ...

它一直挂在 executeFetchRequest 行(我有几个类在或多或少同时执行相同类型的过程)。

按照其他线程中的建议,我将其转换为:

-(void)saveBookmarksToCache:(NSMutableArray *) bookmarkList error:(NSError **)error


    NSFetchRequest *allBookmarks = [[NSFetchRequest alloc] init];
    [allBookmarks setEntity:self.bookmarkDescription];
    [allBookmarks setIncludesPropertyValues:NO]; // Just fetch the Id

    __autoreleasing NSError *reqError = nil;
    // Lock the PersistenStoreCoordinator for the whole process
    @synchronized(self.persistentStoreCoordinator) 
        NSArray *bookmarks = [self.managedObjectContext executeFetchRequest:allBookmarks error:&reqError];

        if (reqError != nil)
            error = &reqError;
        ...

        // Save
        [self.managedObjectContext save:&reqError];
        ...

    

这似乎为我解决了问题。

【讨论】:

以上是关于executeFetchRequest 挂起并且从不返回错误或继续的主要内容,如果未能解决你的问题,请参考以下文章

executefetchrequest 导致崩溃

核心数据 fetchRequest 给出 executeFetchRequest:error: <null> is not a valid NSFetchRequest

for循环随机挂在executeFetchRequest:错误:

核心数据 executeFetchRequest 因 exc_bad_access 而失败

NSInvalidArgumentException',原因:'executeFetchRequest:错误:

从 Xcode 启动 iOS 模拟器并得到黑屏,然后 Xcode 挂起并且无法停止任务