2015-01-21 22 views
6

Bir bağımlılık grafiğinde bazı NSOperation s var:NSOperation'ın bağımlılıklarını nasıl iptal edebilirim?

İşte
NSOperation *op1 = ...; 
NSOperation *op2 = ...; 

[op2 addDependency:op1]; 

Onları koşuyorum edebilirsiniz:

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

Şimdi bunları iptal etmek gerekir. Bir bağımlılık grafiğindeki tüm NSOperation s'nin iptal edildiğinden ve diğer NSOperation s'nin iptal edilmediğinden nasıl emin olabilirim?

(bildiğim kadarıyla söyleyebilirim gibi) diğer iptal etmez ya NSOperation üzerine cancel çağrılması:

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

da iptal olur kuyruğunu iptal ne denedim


op1 ve op2 bağımlılık grafiğinin parçası olmayan işlemler (kuyrukta böyle bir işlem varsa):

[queue cancelAllOperations]; 

Bunu, bir NSOperation bağımlılıklarını yinelemeli olarak gören ve iptal eden bir özel yöntem kullanarak çözdüm.

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

cevap

8

otomatik olarak bağımlılıkları iptal edilirken NSOperation mefhumu var yok: Ben çerçeveyi kavga ediyorum gibi hissediyorum çünkü Ancak, bu çözüm ile mutlu değilim. Bunun nedeni, birden çok NSOperation s aynı NSOperation'a bağımlı olabilir. Bağımlılık ilişkisi kesinlikle tüm bağımlılığı NSOperation s tamamlanıncaya kadar belirli bir NSOperation yürütülmesini geciktirmek için vardır.

Sen NSOperation bir alt sınıfını yazma düşünebilirsiniz:

@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 

Not: Yukarıdaki kod hata özgür olmak garanti edilmez.

+0

Gotcha, +1. Aynı bağımlılık grafiğindeki tüm NSOperation'ların aynı "NSOperationQueue" ye eklendiğinden emin olmaya çalışabilirim (ve bu sırada başka hiçbir şeyin bulunmadığından emin olmak için), böylece sadece [queue cancelAllOperations] 'diyebilirim. –

+1

Aynı anda iptal etmek istediğiniz her bir "NSOperation" grubu için yeni bir 'NSOperationQueue' oluşturduysanız, bunları aynı sistem sırasına koymak için 'underlyingQueue' özelliğini kullanabilirsiniz. 'NSOperationQueue', bir başkasıyla aynı "dispatch_queue_t" üzerinde çalışsa bile, yalnızca bildiği işlemleri iptal edecektir. –

+1

NSOperationQueue belgelerinden: Bir işlemi iptal etmek, işlemin sahip olabileceği bağımlılıkları yok saymasına neden olur.Bu davranış, sıranın işlemin başlangıç ​​yöntemini en kısa zamanda yürütmesini mümkün kılar. Başlangıç ​​yöntemi, sırayla işlemi bitmiş duruma taşır, böylece kuyruktan kaldırılabilir. Ancak, bu işe yaramıyor. – Brett

1

Aynen, aynı sıradaki işlemleri gruplandırmaya çalıştığınız gibi geliyor. Bunu başarmak için, grup başına bir kuyruk kullanarak bunları bölmek en iyisidir. Bu nedenle, her grup için eşzamanlı modda bir NSOperation alt sınıfı oluşturun, bir sıra ekleyin, her alt işlemi sıraya ekleyin. Geçersiz kılma iptal et ve [süper iptal et] ve sonra [self.queue cancelAllOperations].

Bu yaklaşımın büyük bir avantajı, ana sıranın sırasını etkilemeden alt sırayı yeniden ekleyerek işlemleri yeniden deneyebilirsiniz.

İlgili konular