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] в конце каждой задачи

Другие вопросы по тегам