2015-01-21 12 views
6

devo alcuni NSOperation s in un grafico delle dipendenze:Come cancellare le dipendenze di NSOperation?

NSOperation *op1 = ...; 
NSOperation *op2 = ...; 

[op2 addDependency:op1]; 

Ecco come io li sto correndo:

NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
[queue addOperation:op1]; 
[queue addOperation:op2]; 

Ora ho bisogno di annullarle. Come faccio a garantire che tutti gli NSOperation s in un grafico di dipendenze vengano annullati e che non vengano cancellati altri NSOperation s?


che cosa ho provato:

Calling cancel su entrambi i NSOperation non cancella l'altro (per quanto posso dire):

[op1 cancel]; // doesn't cancel op2 
// -- or -- 
[op2 cancel]; // doesn't cancel op1 

Annullamento coda sarebbe anche annullare operazioni che non fanno parte del grafico delle dipendenze di op1 e op2 (se ci sono tali operazioni nella coda):

[queue cancelAllOperations]; 

Quindi ho risolto questo problema utilizzando un metodo personalizzato che esamina in modo ricorsivo le dipendenze di NSOperation e li annulla. Tuttavia, io non sono contento di questa soluzione perché mi sento come sto combattendo il quadro:

- (void)recursiveCancel:(NSOperation *)op 
{ 
    [op cancel]; 
    for (NSOperation *dep in op.dependencies) 
    { 
     [self recursiveCancel:op]; 
    } 
} 

risposta

8

Non esiste una nozione di un NSOperation cancellando automaticamente le dipendenze. Questo perché più NSOperation s possono dipendere dallo stesso altro NSOperation. La relazione di dipendenza esiste rigorosamente per ritardare l'esecuzione di un particolare NSOperation finché tutte le sue dipendenze da NSOperation s sono complete.

Si può non crei una sottoclasse di NSOperation:

@interface NSOperationOneToOne : NSOperation 
- (void)addOneToOneDependency:(NSOperation *)operation; 
- (void)removeOneToOneDependency:(NSOperation *)operation; 
@end 

@implementation NSOperationOneToOne { 
    NSMutableArray *oneToOneDependencies; 
} 
- (void)addOneToOneDependency:(NSOperation *)operation { 
    [oneToOneDependencies addObject:operation]; 
    [self addDependency:operation]; 
} 
- (void)removeOneToOneDependency:(NSOperation *)operation { 
    [oneToOneDependencies removeObject:operation]; 
    [self removeDependency:operation]; 
} 
- (void)cancel { 
    [super cancel]; 
    [oneToOneDependencies makeObjectsPerformSelector:@selector(cancel)]; 
} 
@end 

Nota: il codice di cui sopra non è garantito per essere esente da bug.

+0

Gotcha, +1. Potrei provare ad assicurare che tutti gli 'NSOperation' dello stesso grafico delle dipendenze vengano aggiunti allo stesso' NSOperationQueue' (e assicurati che nient'altro sia in quella coda) in modo che possa semplicemente chiamare '[queue cancelAllOperations]'. –

+1

Se è stato creato un nuovo 'NSOperationQueue' per ogni gruppo di' NSOperation's che si desidera annullare contemporaneamente, è possibile utilizzare la proprietà 'underlyingQueue' per metterli nella stessa coda di sistema. "NSOperationQueue" cancellerà comunque solo le operazioni di cui è a conoscenza, anche se è in esecuzione sullo stesso 'dispatch_queue_t' come un altro. –

+1

Dai documenti NSOperationQueue: L'annullamento di un'operazione fa sì che l'operazione ignori eventuali dipendenze che potrebbe avere.Questo comportamento consente alla coda di eseguire il metodo di avvio dell'operazione il prima possibile. Il metodo start, a sua volta, sposta l'operazione allo stato finito in modo che possa essere rimosso dalla coda. Tuttavia, questo non sembra funzionare. – Brett

1

Mi sembra che si stia tentando di raggruppare le operazioni insieme nella stessa coda. Per ottenere questo è meglio dividerli usando una coda per gruppo. Quindi, per ogni gruppo creare una sottoclasse NSOperation in modalità concorrente, includere una coda, aggiungere ciascuna sotto-operazione alla coda. Annulla l'annullamento e chiama [super cancel] quindi [self.queue cancelAllOperations].

Un enorme vantaggio di questo approccio è che è possibile riprovare le operazioni aggiungendo nuovamente alla sottocoda, senza influire sull'ordine della coda principale.