首页 文章

Dispatch once(dispatch_once)singleton冻结/锁定目标c

提问于
浏览
9

这行代码是在我的 awakeFromFetch 方法中调用的,该方法位于实现 NSManagedObject 的自定义托管对象中 . 这一行特别是调用我的名为 sharedManager 的单例网络管理器类 .

[self setSync:(![[WKNetworkManager sharedManager] objectHasPendingRequests:self.objectID]) ];

dispatch_once块将被命中,如下所示 . 请注意,它以良好的方式实现,如here所示:

enter image description here

然后dispatch_once调用转到once.h并在此处在突出显示的行上冻结:

dipatch_once deeper

这是堆栈跟踪:

stack trace

尝试加载以前保存的网络队列文件时,所有这些都会发生 . 应用程序完全关闭以保存,然后再次启动,然后发生冻结/锁定 .

我甚至尝试使用此代码来解决问题here,并且它不起作用 . 但是改变这个可能无关紧要,因为我原来的dispatch_once代码已经很好地工作了很长时间 . 只是在这种特殊情况下 .

if ([NSThread isMainThread]) 
{
    dispatch_once(&onceToken, ^{
    stack = [[KACoreDataStack alloc] init];});
} 
else 
{
    dispatch_sync(dispatch_get_main_queue(), ^{
    dispatch_once(&onceToken, ^{
    stack = [[KACoreDataStack alloc] init];});
});
}

到目前为止,这些是我解决此类问题的来源:

谢谢你的帮助!

2 回答

  • 6

    该死的儿子,这是一个很好的提问 .

    这里的问题是对dispatch_once的递归调用将会死锁 . 如果您需要确切的详细信息,you can find them with the source here . 所以你需要重写以避免这种情况 .

    我的观点是,有一个建筑失误,无论什么导致这个呼叫 . 你绝对不希望做任何在执行时间内可能无限制的事情,因为关闭并从 dispatch_once 中的磁盘加载东西 . 你想要做的是创建一个可寻址的单例并返回的绝对最小值 . 然后,给它一个"Initializing"的内部状态,并将磁盘加载的东西运送到某个地方的非阻塞队列 . 那样的所有东西都没有"Initialized"状态,或类似的东西 .

  • 0

    感谢alexcurylo的帮助,排除loadFromDisk作业解决了这个问题 . 为了使人们不会感到困惑,只需要使用下面的代码,我就会从磁盘中排队一个加载数组(用作保存的用户请求队列)的作业 . 您可以对任何作业进行排队,例如加载图像等 . 我的sharedManager类中的以下代码(从磁盘加载的位置)起作用,如下所示:

    -(void) loadQueueFromFileByQueueing
    {
      //Create a Queue
      /* Note that fileStrQueue should be added to the .h file as NSOperationQueue *fileStrQueue;*/
      fileStrQueue = [[NSOperationQueue alloc] init];
    
      //Create an  operation which will invoke method loadQueueFromDisk
      NSInvocationOperation * operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadQueueFromDisk) object:nil];
    
      //Add this operation to the queue
      [fileStrQueue addOperation:operation];
    
      //Releasing the above operation as it is already retained by the queue.
      // [operation release]; // If you are using ARC, this won't be necessary
    }
    

相关问题