Чтобы ответить на ваши вопросы:
- Это безопасно, чтобы объединить эту конкретную последовательность операций с зависимостями вы дали с
maxConcurrentOperations = 1
.
- Очередь будет работать
op2
, op3
и op1
или op2
, op1
, op3
если вы изменить порядок зависимостей op1
и op2
.
Нет ничего сложного в цепочке зависимостей, которую вы указали, и NSOperationQueue
может автоматически позаботиться о вещах. Вы можете действительно беспокоиться, если указали круговую зависимость (например, op3
зависит от op1
), или у вас есть операция, которая не добавляется в очередь, и поэтому не может выполняться для удовлетворения зависимости.
Apple, это сказать об отмене в the NSOperationQueue class reference:
Отмена операции вызывает операцию игнорировать любые зависимости он может иметь. Такое поведение позволяет очереди как можно скорее выполнить метод запуска операции. Метод начала, в свою очередь, переводит операцию в законченное состояние, чтобы ее можно было удалить из очереди.
Все подклассы NSOperation должны корректно обрабатывать отмену, сначала проверяя, был ли он отменен, а затем немедленно завершили операцию без каких-либо действий. Если это не сделано, это ошибка, и операции могут выполняться, даже если они были отменены.
(Интересно, что это относится и к NSBlockOperation, чего я не понял. Вам явно нужно проверить self.isCancelled
в блоке).
Я использовал CodeRunner в App Store, чтобы попробовать все это и немного изменил вашу программу. Он воспроизводится ниже.
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
@autoreleasepool {
NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op1"); }];
NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op2"); }];
NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op3"); }];
[op3 addDependency:op2];
[op2 addDependency:op1];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
[queue addOperations:@[op1, op2, op3] waitUntilFinished:YES];
}
}
Для NSBlockOperation
, чтобы обратиться к себе, что нужно сделать это, что немного противно, но выглядит лучше в NSOperation
подклассу, как вы можете обратиться к self
.
__block NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op1 cancelled=%d", op1.cancelled); }];
Я согласен с почти всем, но жду. 'NSBlockOperation' имеет' executeBlocks'. Должен ли я по-прежнему добавлять проверку на отмену, когда они являются отдельными блоками? – Gargo
Очевидно, да, вам нужно явно проверить отмену операции даже в блоках. Вы можете попробовать это самостоятельно, отменив операцию, прежде чем добавить ее в очередь и посмотреть, что произойдет. –
Если очередь, содержащая операцию блока, отменена, она даже не запускается. Вам нужно только проверить isCancelled, если вы делаете что-то медленное внутри блока, как цикл. – malhal