2013-01-01 12 views
6

Sto cercando di eseguire alcuni filtri immagine core nel modo più efficiente possibile. Cercando di evitare avvisi di memoria e arresti anomali, che sto ottenendo durante il rendering di immagini di grandi dimensioni. Sto guardando la Guida alla programmazione delle immagini di base di Apple. Per quanto riguarda il multi-threading, si dice: "ogni thread deve creare i propri oggetti CIFilter, altrimenti l'app potrebbe comportarsi in modo imprevisto."iOS: immagine principale e app multi-thread

Cosa significa?

In effetti sto tentando di eseguire i miei filtri su un thread in background, quindi posso eseguire un HUD sul thread principale (vedi sotto). Ha senso nel contesto di coreImage? Considero che l'immagine principale usa intrinsecamente GCD.

//start HUD code here, on main thread 

// Get a concurrent queue form the system 
dispatch_queue_t concurrentQueue = 
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_async(concurrentQueue, ^{ 

    //Effect image using Core Image filter chain on a background thread 

    dispatch_async(dispatch_get_main_queue(), ^{ 

     //dismiss HUD and add fitered image to imageView in main thread 

    }); 

}); 

Altro da Apple Documenti:

mantenere la sicurezza Discussione

CIContext e CIImage oggetti sono immutabili, il che significa ogni possono essere condivisi in modo sicuro tra i thread. Più thread possono utilizzare lo stesso oggetto GPU o CPU CIContext per eseguire il rendering degli oggetti CIImage . Tuttavia, questo non è il caso per gli oggetti CIFilter, che sono mutabili . Un oggetto CIFilter non può essere condiviso in modo sicuro tra i thread. Se l'app è multithread, ogni thread deve creare i propri oggetti CIFilter . In caso contrario, l'app potrebbe comportarsi in modo imprevisto.

risposta

11

non sono sicuro di come dirlo in modo diverso: ogni thread in background ha bisogno di creare una propria versione degli oggetti CIFilter nella catena dei filtri. Un modo per ottenere questo risultato è quello di creare una copia della catena di filtri per ogni operazione di sfondo che si è dispatch_async(...). Nel codice che hai postato che potrebbe essere simile a questa:

//start HUD code here, on main thread 
// Assuming you already have a CIFilter* variable, created on the main thread, called `myFilter` 
CIFilter* filterForThread = [myFilter copy]; 
// Get a concurrent queue form the system 
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
dispatch_async(concurrentQueue, ^{ 
    CIFilter filter = filterForThread; 

    // Effect image using Core Image filter chain on a background thread 

    dispatch_async(dispatch_get_main_queue(), ^{ 

     //dismiss HUD and add fitered image to imageView in main thread 

    }); 

}); 
[filterForThread release]; 

Quello che succede qui è che filterForThread è una copia di myFilter. Il riferimento filterForThread nel blocco passato a dispatch_async causerà quel blocco per conservare filterForThread, quindi lo scope di chiamata rilascia filterForThread, che effettivamente completa il trasferimento della proprietà concettuale di filterForThread al blocco (poiché il blocco è l'unica cosa rimasta con un riferimento a esso). filterForThread può essere considerato privato del thread in cui viene eseguito il blocco.

Questo dovrebbe essere sufficiente per soddisfare i requisiti di sicurezza del filo qui.

+0

Grazie. Leggerò la tua risposta qualche decina di volte e forse entrerà a fondo :). – Mrwolfy

+1

Ecco un'analogia: se stavi scrivendo un documento e volevi 5 persone diverse per rivederlo/modificarlo per te (allo stesso tempo), non avresti fatto una stampa, messo le 5 persone intorno ad esso e loro provano a fare modifiche simultaneamente; Dovresti fare 5 copie e dare a ciascun revisore/editore il proprio. Stessa idea qui. Stai dando ad ogni thread la propria copia del CIFilter. – ipmcc

+0

OK Grazie. Apprezzo il vostro aiuto. – Mrwolfy