2010-12-13 3 views
4

Ich füge Operationen in die Warteschlange so etwas wie dieseiPhone - eine Verzögerung zwischen den Operationen in der Warteschlange

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]; 

mit der Warteschlange gesetzt ist nur eine Operation zu einem Zeitpunkt zu tun. So wird es die 3 Methoden ohne Verzögerung nacheinander ausführen. Ist das ein Weg, um eine kleine Verzögerung hinzuzufügen, sagen wir 0,5 Sekunden oder was auch immer zwischen den einzelnen Betrieb, so dass anstelle von

doStuff1 
doStuff2 
doStuff3 

die Warteschlange ausgeführt täte

doStuff1 
sleep for X seconds 
doStuff2 
sleep for X seconds 
doStuff3 

?

danke.

+0

Was ist mit dem Hinzufügen einer Operation, die den Schlaf zwischen den anderen Operationen hat? –

+0

welche Operation ist das? Das ist die Frage ... :) – SpaceDog

+0

Erstellen Sie eine NSInvocationOperation, wie Sie es getan haben, aber die ausgeführte Methode führt einen 'sleep' aus. –

Antwort

6

Ohne zusätzliche Code, können Sie nicht wirklich garantieren, dass Ihre NSOperationen seriell ausgeführt werden - wenn Apple ein Multiprozessor-iOS-Gerät veröffentlicht, wird es mehrere Operationen parallel ausführen. Also sollten Sie zuerst die Abhängigkeitskette zwischen Ihren Operationen einrichten. Ich würde vorschlagen, dass Sie dies mit NSOperation - (void)addDependency:(NSOperation *)operation erreichen. Du könntest auch deinen eigenen tollen Sperrcode aufrollen ...

Du kannst dann am Ende jeder deiner doStuff-Methoden einen Schlafmodus (5) hinzufügen. Wenn Sie den Schlaf außerhalb der doStuff Methoden benötigen, einen Schlaf NSOperation erstellen:

- (void)sleepOperationBody; { 
sleep(0.5f); 
} 

NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] 
initWithTarget:self 
selector:@selector(sleepOperationBody) 
object:nil]; 

Das heißt, ohne genauer zu wissen, was Sie passieren müssen, ich glaube, Sie vielleicht nur ein NSOperation benötigen, die alle drei Aufgaben kombiniert und legt einen Schlaf zwischen ihnen. Das wäre sicherlich einfacher Code.

+1

das ist es. Ich werde den Code vereinfachen. Dies ist nur ein erster Entwurf. Aber in Bezug auf Nebenläufigkeit dachte ich den Befehl "[queue setMaxConcurrentOperationCount: 1];" wäre genug, um die Anzahl der parallelen Ausführungen zu begrenzen ... danke. – SpaceDog

+5

> Ohne zusätzlichen Code können Sie nicht wirklich garantieren, dass Ihre NSOperationen seriell ausgeführt werden. Ja, das kannst du, oder? Setzen Sie einfach maxConcurrentOperations auf Ihrer NSOperationQueue auf 1. Das würde es tun, oder? –

+0

Der Aufruf von sleep() wird dazu führen, dass alles in der Operationswarteschlange stoppt !! Selbst wenn Sie gleichzeitige Operationen haben, werden sie wahrscheinlich auch aufhören, wenn sie alle auf demselben Thread laufen. Wenn Sie also nicht innerhalb der Operation einen eigenen Thread erstellen, kann es zu Problemen kommen. Nun, das ist meine Erfahrung, was in der Praxis passiert. Bitte korrigieren Sie mich, wenn ich etwas falsch mache. –

2

Ich habe zwei Möglichkeiten, so etwas zu tun.

Erstens: Lassen Sie den aktuellen Thread auf den Schwanz von DoStuff1, DoStuff2 und DoStuff3 schlafen.

Zweitens: Unterklasse NSOperation und überschreiben Sie die Methode - (void) main. Sie können eine benutzerdefinierte NSOperation mit Parametern von Ziel init und Aktion wie folgt vor:

-(id)initWithTarget:(id)target action:(SEL)action; 

und führen diese Aktion des Ziels in der - (void) Haupt von

[target performSelector:action]; 
[NSThread sleepForTimeInterval:0.05]; 
1

Sie können wie folgt vorgehen Weise

[operation0 addDependancy:operation1]; 
[operation1 addDependancy:operation2]; 

und jetzt hinzufügen [NSThread sleepforTimeInterval: 5], um am Ende jeder Aufgabe

11

Schlaf Mit einer großen Verschwendung eines Threads ist. Das ist schlecht im Sinne von Ghostbusters.

Wenn Sie eine Warteschlange benötigen, die ihre Operationen nicht gleichzeitig ausführt, d. H. Sequenziell, können Sie einfach die Variable maxConcurrentOperationCount auf 1 setzen.

queue.maxConcurrentOperationCount = 1; 

Um zwischen den Operationen pausieren Sie zwei verschiedene Dinge tun könnte:

a) verzögern die Warteschlangen jeder Operation:

//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); 
     }); 

Diese alle Operationen ohne Blockierung Warteschlange wird.

b) Jede Operation hat

- (BOOL)isFinished 

zu implementieren, wie Sie wahrscheinlich bereits wissen.

Wenn Ihre Operation "erledigt" ist, verzögern Sie die Einstellung der Variablen "done" um die gewünschte Verzögerung. Verwenden Sie etwas wie:

// 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"]; 
    }); 

Variante a) garantiert eine Pause zwischen Startzeiten von Operationen. Variante b) garantiert eine Pause zwischen dem Ende einer Operation und dem Beginn einer nächsten Operation.

+3

Das verdient mehr Upvotes! – Klaas

+0

Option b ist hier definitiv die sauberste Lösung und beinhaltet nicht unnötig das Blockieren einer Warteschlange. Hat super funktioniert, vielen Dank! Wenn dies zu viel Setup im Vergleich zu den anderen Lösungen fühlt, würde ich empfehlen, etwas wie PSOperations (https://github.com/pluralsight/psoperations), die die meisten der KVO für Sie wickelt – Marcus

+0

Dies sollte sein Wenn Sie die richtige Antwort verwenden, hat das Verwenden von sleep unbeabsichtigte Konsequenzen, es sei denn, Sie haben einen eigenen Thread erstellt. –

Verwandte Themen