Dispatch once (dispatch_once) singleton hangs / blocks in object c

This line of code is called in my awakeFromFetch method, located inside a custom managed object that implements NSManagedObject . This line, in particular, makes a call to my single-user network manager of the sharedManager class.

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

The dispatch_once block will be removed as shown below. Please note that it is implemented in good form, as shown here :

enter image description here

Then the dispatch_once call goes to once.h, and here it hangs right on the highlighted line:

dipatch_once deeper

Here is the stack trace:

stack trace

All this happens when you try to load a previously saved network queue file. The application completely closes to save, and then starts again, and then this freeze / lock occurs.

I even tried using this code to solve the problem, as suggested here , and it didn't work. But changing this probably doesn't matter, since my original dispatch_once code has worked very well for a long time. It is simple in this particular case.

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

So far, these are my sources for fixing this problem:

Thank you for your help!

+8
ios objective-c singleton xcode grand-central-dispatch
source share
2 answers

Thanks to the help of alexcurylo, a problem was considered in the queue for downloading the forFromDisk job. In order for people not to get confused, it so happened that with this code below I execute a queue with a task that loads an array (which acts as a saved queue of user requests) from disk. You can be in line for any job, for example, upload images / etc. The following code in my sharedManager class (where the boot from disk is loaded) works, as shown here:

 -(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 } 
0
source share

Damn son, this is a good job on an interrogative question.

The problem here is that recursive calls to dispatch_once will be inhibited. If you want accurate information, you can find them here. Therefore, you need to rewrite so that this does not happen.

My opinion is that there is an architectural error related to what leads to this call -loadQueueFromDisk . You absolutely do not want to do something that is potentially unlimited at run time, like going out and loading something from disk inside dispatch_once . What you want to do is the absolute minimum to create an addressable singleton and return. Then give it the internal initialization state and send the material to load the disk into a non-blocking queue somewhere. Thus, everything that does not depend on the material loaded from the disk can continue, and everything that depends on the material loaded from the disk can add itself to the disk loading queue or check every few hundred milliseconds to see if it is still in " Initialized state or something in that direction.

+6
source share

All Articles