2015-01-21 28 views
6

Tôi có một số NSOperation s trong một đồ thị phụ thuộc:Làm cách nào để hủy phụ thuộc của NSOperation?

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

[op2 addDependency:op1]; 

Đây là cách tôi đang chạy chúng:

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

Bây giờ tôi cần phải hủy bỏ chúng. Làm cách nào để đảm bảo rằng tất cả các NSOperation s trong biểu đồ phụ thuộc bị hủy và không có NSOperation giây nào khác bị hủy?


những gì tôi đã cố gắng:

Calling cancel ở hai NSOperation không hủy khác (như xa như tôi có thể nói):

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

hủy hàng đợi cũng sẽ hủy bỏ các hoạt động không thuộc đồ thị phụ thuộc của op1op2 (nếu có bất kỳ hoạt động nào trong hàng đợi):

[queue cancelAllOperations]; 

Vì vậy, tôi đã giải quyết vấn đề này bằng cách sử dụng phương pháp tùy chỉnh đệ quy thông qua các phụ thuộc của NSOperation và hủy chúng. Tuy nhiên, tôi không hài lòng với giải pháp này bởi vì tôi cảm thấy như tôi đang chiến đấu khuôn khổ:

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

Trả lời

8

Có không tồn tại một khái niệm về một NSOperation tự động hủy bỏ sự phụ thuộc của nó. Điều này là do nhiều NSOperation s có thể phụ thuộc vào cùng một khác NSOperation. Mối quan hệ phụ thuộc tồn tại nghiêm ngặt để trì hoãn thực hiện một NSOperation cụ thể cho đến khi tất cả phụ thuộc của nó NSOperation s hoàn tất.

Bạn có thể xem xét việc viết một lớp con của 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 

Note: Đoạn mã trên là không đảm bảo được lỗi-miễn phí.

+0

Gotcha, +1. Tôi có thể cố gắng đảm bảo rằng tất cả 'NSOperation' từ cùng một biểu đồ phụ thuộc được thêm vào cùng một 'NSOperationQueue' (và đảm bảo rằng không có gì khác nằm trong hàng đợi đó) để tôi có thể gọi' [queue cancelAllOperations] '. –

+1

Nếu bạn đã tạo một 'NSOperationQueue' mới cho mỗi nhóm' NSOperation' mà bạn muốn hủy cùng một lúc, bạn có thể sử dụng thuộc tính 'innerQueue' để đặt chúng vào cùng một hàng đợi hệ thống. 'NSOperationQueue' sẽ vẫn chỉ hủy bỏ các hoạt động mà nó biết, ngay cả khi nó đang chạy trên cùng một' dispatch_queue_t' như một phương thức khác. –

+1

Từ tài liệu NSOperationQueue: Hủy hoạt động khiến cho hoạt động bỏ qua bất kỳ phụ thuộc nào mà nó có thể có.Hành vi này làm cho hàng đợi có thể thực hiện phương thức bắt đầu của hoạt động càng sớm càng tốt. Phương thức bắt đầu, lần lượt, di chuyển hoạt động đến trạng thái kết thúc để nó có thể được loại bỏ khỏi hàng đợi. Tuy nhiên, điều này dường như không hoạt động. – Brett

1

Âm thanh với tôi như bạn đang cố nhóm các hoạt động lại với nhau trong cùng một hàng đợi. Để đạt được điều đó, tốt nhất là chia chúng ra bằng cách sử dụng hàng đợi cho mỗi nhóm. Vì vậy, đối với mỗi nhóm tạo một lớp con NSOperation ở chế độ đồng thời, bao gồm một hàng đợi, hãy thêm từng hoạt động phụ vào hàng đợi. Ghi đè hủy và gọi [super cancel] rồi [self.queue cancelAllOperations].

Một lợi thế lớn của phương pháp này là bạn có thể thử lại hoạt động bằng cách thêm lại vào hàng đợi phụ, mà không ảnh hưởng đến thứ tự của hàng đợi chính.

Các vấn đề liên quan