6

Pracując z jakimś kodem, przechodzę przez pętle uruchomieniowe, do których jestem nowy, wewnątrz NSOperation s.Korzystanie z NSThread sleep in a NSOperation

S s są zajęty pobieranie danych - i gdy są one zajęte, jest kod, aby czekać na zakończenie pobierania, w postaci NSRunLoop s i wątku wątku.

Kod ten jest w szczególności interesujące dla mnie:

while (aCertainConditionIsTrue && [self isCancelled]==NO) { 
    if(![[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]){ 
     [NSThread sleepForTimeInterval:1.0]; 
    } 
} 

Czytałem o pętlach Uruchom i runMode:beforeDate: będzie czekać na źródła wejściowego lub timeout. Chociaż nie jestem w 100%, to co liczy się jako źródło danych wejściowych.

Przy pierwszym wykonaniu tego zawsze zwraca NO i uderza w sleepForTimeInterval:. Czy to źle?

W konkretnej klasie narzędziowej trafia ona bardzo często - raz na każdy wątek - co znacząco szkodzi wydajności.

Jakieś lepsze rozwiązania tego problemu lub porady?

Odpowiedz

2

Spanie blokuje wątek. Być może zmieniasz swój kod, aby użyć performSelector: withObject: afterDelay. W ten sposób wątek może nadal działać.

... 
    done = NO; 
    [self checkDoneCondition:nil]; 
    ... 

- (void)checkDoneCondition:(id)object { 
    if (aCertainConditionIsTrue && [self isCancelled]==NO) { 
     if(...) { 
      [self performSelector:@selector(checkDoneCondition:) withObject:[con error] afterDelay:1.0]; 
     } else { 
      done = YES; 
     } 
    } 
} 
1

Wygląda na to trzeba użyć współbieżne NSOperation. Tutaj jest odpowiednia część w docs Apple:

W przeciwieństwie do nie-jednoczesnych operacji, czyli synchronicznie, A równoczesna praca przebiega asynchronicznie. Innymi słowy, gdy wyłączysz metodę początkową operacji współbieżnej, ta metoda może zwrócić się, zanim zakończy się odpowiednie zadanie. Może się to zdarzyć , ponieważ obiekt operacji utworzył nowy wątek do wykonania zadania lub dlatego, że operacja nazywała się funkcją asynchroniczną. Nie ma to znaczenia, jeśli operacja jest w toku, gdy sterowanie powraca do osoby dzwoniącej, tyle tylko, że może to trwać. (...) W przypadku operacji współbieżnej metoda uruchamiania jest odpowiedzialna za rozpoczęcie operacji w sposób asynchroniczny. Niezależnie od tego, czy spawnujesz wątek , czy wywołujesz funkcję asynchroniczną, robisz to z tej metody. Po uruchomieniu operacji metoda uruchamiania powinna również zaktualizować stan wykonania operacji zgodnie z metodą isExecuting . Robi się to poprzez wysyłanie powiadomień KVO dla ścieżki klucza wykonania klucza, która pozwala zainteresowanym klientom wiedzieć, że operacja jest już uruchomiona. Twoja metoda isExecuting musi również zwracać status w sposób bezpieczny dla wątków.

(od https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html)

Innymi słowy, można zastąpić metodę -start w podklasie NSOperation i mają ivar dla właściwości executing i finished. Ta metoda rozpocznie pobieranie w oddzielnym wątku. Po rozpoczęciu pobierania ustaw flagę executing i uruchom KVO.KIEDY kończy się to w tym wątku, robisz to samo z finished i executing. Wydaje się to skomplikowane, ale w rzeczywistości jest dość proste.

Zobacz także to pytanie na przepełnieniu stosu z doskonałym wyjaśnieniem: Subclassing NSOperation to be concurrent and cancellable

Powiązane problemy