iPhone - задержка между операциями в очереди
Я добавляю операции в очередь, используя что-то вроде этого
NSInvocationOperation *operation0 = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(doStuff1)
object:nil];
[queue addOperation:operation0];
[operation0 release];
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(doStuff2)
object:nil];
[queue addOperation:operation1];
[operation1 release];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(doStuff3)
object:nil];
[queue addOperation:operation2];
[operation2 release];
Очередь настроена на выполнение только одной операции за раз. Таким образом, он будет запускать 3 метода без задержки, один за другим. Это способ добавить небольшую задержку, скажем, 0,5 секунды или что-то еще между каждой операцией, чтобы вместо выполнения
doStuff1
doStuff2
doStuff3
очередь будет делать
doStuff1
sleep for X seconds
doStuff2
sleep for X seconds
doStuff3
?
Благодарю.
4 ответа
Без дополнительного кода вы не сможете гарантировать, что ваши NSOperations будут работать последовательно - если Apple выпустит многопроцессорное устройство iOS, она будет выполнять несколько операций параллельно. Итак, во-первых, вы должны установить цепочку зависимостей между вашими операциями. Я хотел бы предложить, чтобы вы достигли этого с помощью NSOperation's - (void)addDependency:(NSOperation *)operation
, Вы также можете свернуть свой собственный причудливый код блокировки...
Затем вы можете добавить sleep(5) в конец каждого из ваших методов doStuff. Если вам нужен сон вне методов doStuff, создайте NSOperation сна:
- (void)sleepOperationBody; {
sleep(0.5f);
}
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(sleepOperationBody)
object:nil];
Тем не менее, не зная более подробно, что вам нужно, я думаю, что вам, возможно, просто нужна одна операция NSO, которая объединяет все три задачи и укладывает сон между ними. Это, конечно, был бы более простой код.
Использование сна - большая трата нити. Это плохо в смысле охотников за привидениями.
Если вам нужна очередь, которая выполняет свои операции не одновременно, то есть последовательно, вы можете просто установить для ее переменной maxConcurrentOperationCount значение 1.
queue.maxConcurrentOperationCount = 1;
Чтобы сделать паузу между операциями, вы можете сделать две разные вещи:
а) Задержка в очереди каждой операции:
//loop over the operations to be queued with and index
double delayInSeconds = 2.0 * index;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
queue.addOperation(operation at index);
});
Это поставит все операции в очередь без блокировки.
б) каждая операция должна быть реализована
- (BOOL)isFinished
как вы, наверное, уже знаете.
Если ваша операция "выполнена", просто отложите установку переменной "выполнено" на желаемую задержку. Используйте что-то вроде:
// Operation is done with its work, but we tell the Queue only after 2 seconds, so the queue will start the next operation later
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
__weak __typeof(self)weakSelf = self;
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[weakSelf willChangeValueForKey:@"isExecuting"];
[weakSelf willChangeValueForKey:@"isFinished"];
weakSelf.executing = NO;
weakSelf.finished = YES;
[weakSelf didChangeValueForKey:@"isFinished"];
[weakSelf didChangeValueForKey:@"isExecuting"];
});
Вариант а) гарантирует паузу между временами запуска операций. Вариант б) гарантирует паузу между окончанием операции и началом следующей операции.
У меня есть два способа сделать это.
Первый: пусть текущий поток спит на хвосте doStuff1, doStuff2 и doStuff3.
Второе: подкласс NSOperation и переопределить метод -(void)main. Вы можете запустить пользовательскую NSOperation с параметрами target и action, такими как:
-(id)initWithTarget:(id)target action:(SEL)action;
И выполнить это действие цели в - (void) основной
[target performSelector:action];
[NSThread sleepForTimeInterval:0.05];
Вы можете сделать как в следующем порядке
[operation0 addDependancy:operation1];
[operation1 addDependancy:operation2];
и теперь добавьте [NSThread sleepforTimeInterval:5] в конце каждой задачи