2016-06-27 12 views
6

Ich habe NSOperationQueue bereits erfolgreich in der Anwendung implementiert.Wie setze ich den Timeout-Vorgang NSOperationQueue in iOS fort?

Ich habe eine Warteschlange, die 1000 von NSOperations wie unten haben könnte.

@interface Operations : NSOperation 

@end 

@implementation Operations 

- (void)main 
{ 
    NSURL *url = [NSURL URLWithString:@"Your URL Here"]; 

    NSString *contentType = @"application/json"; 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 
    [request setHTTPMethod:@"POST"]; 
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; 
    NSError *err = nil; 

    NSData *body = [NSJSONSerialization dataWithJSONObject:postVars options:NSJSONWritingPrettyPrinted error:&err]; 

    [request setHTTPBody:body]; 
    [request addValue:[NSString stringWithFormat:@"%lu", (unsigned long)body.length] forHTTPHeaderField: @"Content-Length"]; 

    [request setTimeoutInterval:60]; 

    NSHTTPURLResponse *response = nil; 
    NSError *error = nil; 

    NSData *resData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 
} 

@end 

Jetzt für diese Warteschlange ich alle 1000 Operationen gleichzeitig hinzufügen. Ich füge Operation wie folgt hinzu.

Operations *operation = [[Operations alloc]init]; 
[downloadQueue addOperation:operation]; 

Nun, was Zeitintervall passiert ist 60 als [request setTimeoutInterval:60]

wie nach 60 Sekunden Also denken Sie, wenn 300 Operationen von 1000 Operationen beendet sind dann andere 700 Operationen Anfragezeitüberschreitungsfehler werfen.

Also was soll ich in diesem Fall tun.

Kann ich fehlgeschlagene Operationen fortsetzen? Oder ich sollte wieder Betrieb machen und es in der Warteschlange hinzufügen.

Gibt es einen besseren Mechanismus als diesen?

Antwort

3

Meine anfängliche Neigung wäre, ja, erstellen Sie einfach neue Operationen für die zeitlich befristeten Anfragen und werfen Sie sie zurück in die Warteschlange. Es fühlt sich einfach einfacher an, da Sie bereits Logik für das Hinzufügen dieser Operationen für Ihre Anforderungen haben. JEDOCH:

  1. Achten Sie darauf, nicht in eine Art Endlosschleife zu geraten. Wenn nur EINER von ihnen aus irgendeinem Grund auf unbestimmte Zeit ausfällt, wird Ihre Warteschlange weiter tuckern. Ich würde eine Fehleranzahl beibehalten, so dass Sie nach einer endlichen Anzahl von Versuchen nicht mehr versuchen, eine Anfrage zu wiederholen.

  2. Wenn Sie wissen, dass eine große Anzahl immer fehlschlagen wird, denken Sie darüber nach, sie auf irgendeine Weise zu dosieren. Eine Option wäre eine Kette von Abhängigkeiten. z.B. Sie könnten versuchen, 200 Ihrer Ops, eine "warten" NSOperation, die nächsten 200, eine andere "warten" NSOperation, eine andere "warten" -Op, etc. Machen Sie die erste Wartezeit op abhängig von diesen ersten 200 Anfragen. Dann machen Sie die nächsten 200 hängen von dieser ersten Warte op, und so weiter:

    • [Charge 1: ersten 200 Anfragen]
    • [warten 1: op, die für alle Batch wartet 1]
    • [ 2 batch: next 200, die jeweils darauf wartet, wait 1]
    • [wAIT 2: op, die für alle Stapel wartet 2]
    • [Charge 3: next 200, die jeweils darauf wartet Warte 2]
    • usw.
  3. Grundsätzlich wie 2, aber statt einer "Warte" -Op, haben Sie eine "fertig" -Op.Nehmen wir an, Sie haben ein Array von 1000 zu sendenden Anfragen: Toss 200 in die Warteschlange, dann eine "done" -Option, die von diesen 200 abhängt. Wenn das "done" -Operativ ausgeführt wird (per Definition, NACHDEM diese 200 erledigt sind), kann es Ziehen Sie dann die nächsten 200 aus dem Array und werfen Sie sie hinein (plus eine neue "done" -Op).

(vielleicht sogar als die Warte/done op "Pause" machte ein paar Sekunden, um dem Server eine Verschnaufpause zu geben)

Mit anderen Worten, mit # 2 und # 3, ich sage " sprengen 200 auf einmal, warten Sie, dann sprengen Sie die nächsten 200, warten Sie usw. " (200 ist willkürlich von mir, wissen Sie besser als ich, was die beste Zahl für Ihre Situation ist)

2

Sie können die NSURLConnectionDelegate-Methode connection:didFailWithError: implementieren, um zu überprüfen, ob die synchrone Anforderung fehlgeschlagen ist und ob der Fehler darin bestand, dass die Anforderung abgelaufen ist. Wiederholen Sie dann die Verbindung im Delegaten-Rückruf.

Ich sollte beachten, dass Apple die Verwendung von NSURLSession über NSURLConnection stark fördert, da viele Methoden in NSURLConnection jetzt veraltet sind.

+0

Können Sie bitte einen Hinweis liefern, die ich folgen sollte? –

+0

@JayeshSojitra sicher: [NSURLConnectionDelegate Dokumentation] (https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLConnectionDelegate_Protocol/) [NSURLConnection zu NSURLSession Migration Guide] (https: //www.objc. io/issues/5-ios7/von-nsurlconnection-to-nsurlsession /) – JAL

2

Der erste Punkt ist - lassen Sie sie nicht laufen alle zur gleichen Zeit! Sie können eine mobile Datenverbindung problemlos überfluten, wenn Sie versuchen, selbst 10 Anfragen gleichzeitig auszuführen. Stellen Sie also vor allem anderen die maxConcurrentOperationCount der Warteschlange auf etwa 5.

Dies allein wird wahrscheinlich Ihr Problem massiv reduzieren und Sie müssen möglicherweise nichts anderes tun.

Sie sollten auch wirklich mit NSURLSession aussehen, und auf diese Weise können Sie auch die Operation Warteschlange entfernen und HTTPMaximumConnectionsPerHost verwenden, um zu steuern, wie viele Anfragen zur gleichen Zeit gemacht werden.

Wenn Sie immer noch einen Fehler dann einer der ‚rekursiven‘ Optionen wie andere Antworten diskutieren eine praktikable Lösung ist. Ich würde der Operationsunterklasse einen Versuchszähler hinzufügen, um die Nachverfolgung zu erleichtern. Wenn dies fehlschlägt, überprüfe, wie oft der Fehler aufgetreten ist, und entscheide, ob eine neue Kopie des Vorgangs erstellt und zur Warteschlange hinzugefügt oder eine Warnung ausgelöst werden soll .

Verwandte Themen