2015-02-18 11 views
8

Questa riga di codice viene chiamata nel mio metodo awakeFromFetch situato all'interno di un oggetto gestito personalizzato che implementa NSManagedObject. Questa linea, in particolare, sta effettuando una chiamata alla mia classe di gestore di rete singleton denominata sharedManager.Dispatch una volta (dispatch_once) singleton si blocca/blocca nell'obiettivo c

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

Il blocco dispatch_once verrà colpito come mostrato di seguito. Si noti che è implementato in senso buono, come è mostrato here:

enter image description here

La chiamata dispatch_once poi va a once.h e qui si blocca proprio sulla linea evidenziata:

dipatch_once deeper

Ecco la traccia dello stack:

stack trace

Tutto questo accade quando si tenta di caricare un file di coda di rete precedentemente salvato. L'applicazione viene chiusa completamente per salvare, quindi viene avviata nuovamente e quindi si verifica questo blocco/blocco.

Ho anche provato a utilizzare questo codice per risolvere il problema come suggerito here e non ha funzionato. Ma cambiare questo probabilmente non importa in ogni caso, come il mio codice dispatch_once originale ha funzionato bene per molto tempo. È solo in questo caso particolare.

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

Finora, queste sono le mie fonti per la risoluzione di questo tipo di problema:

Grazie per il vostro aiuto!

risposta

0

Grazie all'aiuto di alexcurylo, è stato risolto il problema con l'accodamento del carico. In modo che le persone non siano confuse, si dà il caso che con questo codice di seguito metto in coda un lavoro che carica un array (che funge da coda salvata di richieste dell'utente) dal disco. Si potrebbe essere messa in coda qualsiasi lavoro, come ad esempio il caricamento delle immagini/ecc Il seguente codice nella mia classe sharedManager (dove il carico da disco viene chiamato) ha lavorato, come viene mostrato qui:

-(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 
} 
6

Dannatamente figlio, questo è un bel lavoro di domande-domande.

Il problema qui è che le chiamate ricorsive a dispatch_once si bloccano. Se vuoi i dettagli esatti, you can find them with the source here. Quindi è necessario riscrivere per evitarlo.

La mia opinione è che ci sia un passo falso architettonico con qualunque cosa porti a questa chiamata -loadQueueFromDisk. Si deve assolutamente fare non voler fare tutto ciò che è potenzialmente illimitato nei tempi di esecuzione come andare fuori e caricare qualcosa dal disco all'interno di uno dispatch_once. Quello che vuoi fare è il minimo indispensabile per creare un singleton indirizzabile e tornare indietro. Quindi, dagli uno stato interno di "Inizializzazione" e spedisci il materiale che carica il disco su una coda non bloccante da qualche parte.In questo modo tutto ciò che non dipende dalle cose caricate dal disco può continuare e tutto ciò che dipende dalle cose caricate dal disco può aggiungersi alla coda in cui il caricamento del disco è attivo, oppure controllare ogni centinaia di millisecondi per vedere se è ancora in uno stato "Inizializzato" o qualcosa del genere.

+0

Grazie! Penso che tu sia certamente interessato all'architettura. L'intero caricamento da disco è stato aggiunto dopo che l'app è stata progettata e ovviamente non sta giocando bene con esso. WKNetworkManager (sharedManager) chiama '[self loadQueueFromDisk];'. Quindi, a sua volta, creando gli oggetti decodificati, tali inizializzazioni dell'oggetto attivano le chiamate a sharedManager. Questo potrebbe certamente essere problematico. La soluzione collegata sembra ingombrante. Pensi che fare una dichiarazione di blocco di loadQueueFromDisk per delegare l'attività a un altro thread funzionerebbe? – Marcel

+0

Se ti piace la domanda, invitala! – Raspu

+1

Bene, Core Data e threading, che possono complicarsi rapidamente. La mia prima inclinazione all'inizializzazione del Core Data di questo tipo è di lanciarla nella coda GCD a bassa priorità 'dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_LOW, 0),^{[self loadQueueFromDisk];});' quindi viene preso in considerazione una volta le code di priorità alta e normale sono vuote. Poiché è probabile che sia il comportamento desiderato durante l'avvio. –