2009-10-03 10 views
6

Ich arbeite mit etwas Code, der eine Reihe asynchroner Operationen mit verschiedenen Rückrufen durchführt; Snow Leopard hat dies mit Blöcken und GCD unglaublich einfach gemacht.Wie leicht ist NSOperationQueue auf Snow Leopard?

Ich rufe NSTask von einem NSBlockOperation etwa so:

[self.queue addOperationWithBlock:^{ 
    NSTask *task = [NSTask new]; 
    NSPipe *newPipe = [NSPipe new]; 
    NSFileHandle *readHandle = [newPipe fileHandleForReading]; 
    NSData *inData = nil; 
    [task setLaunchPath:path]; 
    [task setArguments:arguments]; 
    [task launch]; 

    while ((inData = [readHandle availableData]) && [inData length]) { 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      // callback 
     }]; 
    } 

    [task waitUntilExit]; 
}]; 

Dieser Ansatz funktioniert perfekt. Es ist wie Magie, solange meine Callbacks die Parallelität korrekt behandeln.

Nun möchte ich in der Lage sein, einige dieser Anrufe zu koaleszieren; Dies befindet sich in der Refresh-Methode eines Modellobjekts und kann sehr lange dauern. Wenn der Benutzer auf den Aktualisierungsbutton klopft, sollte der Rechner und all das nicht gebunden werden.

Ich kann hier ein Implementierungsdilemma sehen. Ich kann eine ganze Reihe von Warteschlangen erstellen - eine pro Anruftyp - und ihre Anzahl der gleichzeitigen Vorgänge auf 1 setzen und dann -cancelAllOperations anrufen, wenn es Zeit für einen neuen Anruf ist.

Alternativ könnte ich manuelle Buchführung durchführen, auf der derzeit Anrufe ausgeführt werden und eine einzelne Warteschlange pro Modellobjekt verwalten (wie ich es tue), oder ich könnte noch weiter gehen und eine globale Warteschlange verwenden.

Wie schwer ist NSOperationQueue? Ist das Erstellen vieler Warteschlangen eine schlechte Architekturentscheidung? Gibt es eine bessere Möglichkeit, diese Aufgaben zusammenzuführen?

+2

FYI, du leckst deine NSTask und deine NSPipe. + new ist äquivalent zu + alloc/-init, was bedeutet, dass du für die Freigabe verantwortlich bist ... was du nie tust (in deinem Code oben). (es sei denn natürlich, Sie verwenden GC) –

+1

Es ist ein Snow Leopard-only-Programm. Ich würde sicherlich hoffen, dass Ihr brandneuer Snow-Leopard-Code nur Müll ist. :-D –

Antwort

8

Wenn Sie sich Sorgen um die Leistung machen, raten Sie nicht: Messen und beheben Sie alle Engpässe, die Sie finden. Das Hinzufügen von Warteschlangen ist einfach. Probieren Sie es aus und sehen Sie, welche Instrumente Sie über die Auswirkungen auf die Leistung informieren.

Der Hauptgrund für die Erstellung mehrerer Warteschlangen ist, wenn Sie einen Grund haben, sie zu starten und zu stoppen. Wenn Sie nur die Vorteile von libdispatch nutzen möchten, können Sie dies einfach durch Hinzufügen von Operationen zur Hauptwarteschlange erreichen.

0

Verwenden Sie so viele Warteschlangen wie Sie möchten. Sie sind hier, um logische Teile Ihres Programms zu trennen. Ich denke nicht, dass Sie sich über die Performance Sorgen machen sollten, solange Sie nicht Hunderte von Warteschlangen pro Sekunde zuweisen.

+0

Webseite? Was hat das mit Websites zu tun? –

+0

Danke, es ist noch zu früh am Morgen. :) –

1

Sie können mehrere Blöcke zu einer NSBlockOperation hinzufügen, die gleichzeitig ausgeführt wird und abgebrochen werden kann, indem den enthaltenden Vorgang abbricht. Solange Ihre individuellen Aufgaben nicht serialisiert werden müssen, kann dies funktionieren.

+0

Das ist nicht was die Dokumente sagen: "Die NSBlockOperation-Klasse ist eine konkrete Unterklasse von NSOperation, die die gleichzeitige Ausführung von einem oder mehreren Blöcken verwaltet." http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/NSBlockOperation_class/Reference/Reference.html –

+0

Jim, du bist absolut richtig. Antwort aktualisiert Vielen Dank. –