2016-06-22 31 views
0

Ich möchte ein paar Netzwerkmethoden mit NSOperation für jede von ihnen ausführen, und fügen Sie die Operationen zu einer NSOperationQueue hinzugefügt ein Back-Thread, ich möchte die NSOperationen serialisiert passieren.So verwenden Sie NSOperationQueue und NSOperation, um regelmäßig serialisierte Download-Aufgaben mit einem NSTimer auf dem Hintergrund zu starten Thread

Der Aufruf, der die NSOperation-Warteschlange erstellt, wird in regelmäßigen Abständen alle 30 Sekunden mit einem NSTimer aufgerufen.

ist hier ein Code so weit snipped:

NSTimer *timer; 
NSOperationQueue *bgQueue; 

- (void)startdDownloadLoop{ 

    if (![self.timer isValid]){ 

     self.bgQueue = [[NSOperationQueue alloc] init]; 
     self.timer = [NSTimer scheduledTimerWithTimeInterval:30.0 
                 target:self 
                selector:@selector(updateDB) 
                userInfo:nil 
                repeats:YES]; 

    } 

} 

- (void)updateDB{ 

    //  Next code was removed since si similar to the call `[self.bgQueue cancelAllOperations];`, as @robinkunde suggested 
    //  for (NSOperation *operation in [self.bgQueue operations]) { 
    //   if (operation.isExecuting) { 
    //    [operation cancel]; 
    //   } 
    //  } 

    [self.bgQueue cancelAllOperations]; 


    self.bgQueue = [[NSOperationQueue alloc] init]; 
    self.bgQueue.maxConcurrentOperationCount = 1; 

    NSBlockOperation *blockOp1 = [NSBlockOperation blockOperationWithBlock:^{ 
     [NetworkManager downloadCars]; 
    }]; 

    NSBlockOperation *blockOp2 = [NSBlockOperation blockOperationWithBlock:^{ 
     [NetworkManager downloadPartsForAllCars]; 
    }]; 

    NSBlockOperation *blockOp3 = [NSBlockOperation blockOperationWithBlock:^{ 
     [NetworkManager downloadEachPathSpecs]; 
    }]; 

    [self.bgQueue addOperation:blockOp1]; 
    [self.bgQueue addOperation:blockOp2]; 
    [self.bgQueue addOperation:blockOp3]; 

} 

Die NetworkManager Methoden sind POST/GET-Methoden mit Abschluss-Handler, dass, nachdem sie fertig ist das Herunterladen sie das Datum in DB speichern und dann die Benutzeroberfläche aktualisiert eine Verwendung Benachrichtigung.

Update:

Da die Verwirrung, dachte ich, meine eigentliche Frage in Bezug auf den Code als Brachen schreiben:

1- Wenn die Ausführung des NSOperationQueue Serien sein wird?

2 - wenn ich rufe die [operation cancel] wird die Ausführung der Operation stoppen?

3 - Wenn ich die cancelAllOperations aufrufen und die ich re-init es ist die richtige Art, die aktuelle NSOperationQueue zu löschen?

+0

Es wird wahrscheinlich nicht tun, was Sie wollen. Vermutlich wird jede der 'download ...' Methoden asynchron ausgeführt. Wenn dies der Fall ist, wird der Block abgeschlossen, sobald der Netzwerkvorgang beendet ist, und der nächste gesendete Block wird ausgeführt, obwohl der erste Download-Vorgang noch nicht abgeschlossen ist. Sie wären wahrscheinlich besser dran mit einer dispatch_group, oder noch besser Push-Benachrichtigungen statt polling, die in Bezug auf Batterie- und Netzwerkverkehr teuer ist – Paulw11

+0

Bis zum Abbrechen Operationen, ist es an jedem Block zu prüfen, die Blöcke 'isCancelled' Eigenschaft und Arbeit einstellen, wenn angemessen.Die Operationswarteschlange kann eine Operation nicht wirklich abbrechen, sie legt lediglich fest, dass die Eigenschaft der Operation anzeigt, dass sie sich selbst abbrechen soll. Siehe http://stackoverflow.com/questions/8113268/how-to-cancel-nblockoperation – Paulw11

Antwort

1

1) Sie können die Eigenschaft maxConcurrentOperationCount in der Warteschlange auf 1 setzen, um die serielle Ausführung sicherzustellen.

2) Dies setzt nur die isCancelled Eigenschaft auf den Vorgang. Die Aktion muss auf diese Änderung reagieren und sich selbst in den fertigen Zustand versetzen, damit sie aus der Warteschlange entfernt werden kann.

Wie für Ihr konkretes Beispiel: NSBlockOperation gilt als beendet, wenn alle angehängten Blöcke zurückgegeben wurden. Das bedeutet, dass, wenn die Aufrufe von NetworkManager nicht synchron sind, der Block sofort zurückkehrt, die Operation als beendet gilt und die Warteschlange die nächste Operation startet. Es ist durchaus möglich, dass die Warteschlange beendet wird, bevor der erste Netzwerkvorgang abgeschlossen ist. Wenn Sie sie nacheinander ausführen wollen, ist dies nicht der richtige Weg.

Sie könnten synchrone Netzwerkoperationen verwenden, aber das würde Ihnen immer noch nicht erlauben, sie abzubrechen.

Schauen Sie sich diese Antwort: NSURLSession with NSBlockOperation and queues

3) Dies bezieht sich auf 2). Alle cancelAllOperations ist die isCancelled Eigenschaft für alle Operationen festgelegt. Bis diese Operation beendet ist, wird die Warteschlange weiterhin existieren. Das Erstellen einer neuen Warteschlange für dieselbe Eigenschaft ändert das nicht.

+0

Danke @robinkunde für Sie prompte Antwort Ich werde meinen Code entsprechend ändern, indem Sie die extra for-Schleife entfernen, aber dann ist meine Frage, wie kann Ich zwinge, eine NSOperation zu stoppen, die noch läuft? –

+0

Ich habe meine Antwort aktualisiert. – robinkunde