2013-05-10 13 views
5

Przeczytałem wiele wpisów na temat NSRunLoop, takich jak this, this, this. Ale nie może dowiedzieć się, co faktycznie robi NSRunLoopCo robi NSRunLoop?

Co ja zwykle zobaczyć to wątek pracownik

wthread = [[NSThread alloc] initWithTarget:self selector:@selector(threadProc) object:nil]; 
[wthread start]; 

z NSRunLoop środku

- (void)threadProc 
{ 
    NSAutoreleasePool* pool1 = [[NSAutoreleasePool alloc] init]; 
    BOOL isStopped = NO; 
    NSRunLoop *runloop = [NSRunLoop currentRunLoop]; 
    [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 

    while (!isStopped) 
    { 
     { 
      NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init]; 
      [runloop runMode:NSDefaultRunLoopMode 
             beforeDate:[NSDate distantFuture]]; 

      [pool2 release]; 
     } 
    } 

    [pool1 release]; 
} 

A głównym wątku przechodzi jakąś pracę do tego wthread

[self performSelector:@selector(someWork:) onThread:wthread withObject:nil waitUntilDone:NO]; 

Pod względem przekazywania pracy z głównego wątku do wor Wątek, widzę, że wielu ludzi to robi. Dlaczego potrzebujesz NSRunLoop tutaj? Co to robi ?

Przeczytałem, że NSRunLoop służy do zarządzania zdarzeniami, dlaczego nie ma nic oprócz wywoływania runMode wewnątrz threadProc?

+0

myślę o nim jako o fantazyjnych while (true) {// insert zadanie do zrobienia tutaj}, gdzie możesz dynamicznie dodawać kod do wykonania (zdarzenia, praca, gniazda itp.). Runloop nie jest naprawdę pusty, port został dołączony do pętli, jest formą komunikacji międzyprocesowej. – foFox

+0

Znalazłem ten http://bou.io/RunRunLoopRun.html, aby był przydatny również – onmyway133

Odpowiedz

3

Przykład, który pokazałeś, to idiom kakao do tworzenia wątku, który będzie kontynuowany po wyjściu z metody -threadProc. Czemu?

Ponieważ:

  • utworzeniu instancji NSRunLoop ma co najmniej jedno źródło sygnału wejściowego ([NSMachPort port])
  • już wyraźnie zaczął pętlę biegu z runMode:beforeDate

Bez dodawania źródło wejściowe i jawnie uruchamiające pętlę uruchamiania, wątek zakończyłby się.

Nawiasem mówiąc, mimo że pętle uruchomieniowe są nadal niezbędne do zarządzania zdarzeniami i pewnymi zadaniami asynchronicznymi, nie będę postrzegał NSThread jako domyślnego sposobu projektowania najbardziej asynchronicznych prac w aplikacji Cocoa w dzisiejszych czasach. GCD jest znacznie czystszym sposobem zamykania pracy w tle.

EDIT:

Składanie prac do kolejki szeregowego w GCD:

@interface Foo : NSObject 
@end 

@implementation Foo { 
    dispatch_queue_t _someWorkerQueue; 
} 

- (id)init { 
    self = [super init]; 
    if(!self) return nil; 

    _someWorkerQueue = dispatch_queue_create("com.company.MyWorkerQueue", 0); 
    return self; 
} 

- (void)performJob { 
    dispatch_async(_someWorkerQueue, ^{ 
     //do some work asynchronously here 
    }); 

    dispatch_async(_someWorkerQueue, ^{ 
     //more asynchronous work here 
    }); 
} 
@end 
+0

1) Dlaczego więc istnieje pętla wewnątrz threadProc? 2) GCD przeniesie pracę do wszystkich dostępnych/nieznanych wątków, ale NSRunLoop zapewni, że wszystkie prace zostaną przeniesione do tego samego wątku roboczego, prawda? – onmyway133

+0

Aby zapewnić mechanizm zakończenia pętli uruchamiania - gdy flaga 'isStopped' jest ustawiona (chociaż nie jest to pokazane w kodzie ...) – FluffulousChimp

+0

2) zobacz poprawioną odpowiedź dla podejścia GCD do opisywanego przypadku użycia. – FluffulousChimp

3

Wiele dzieje się za sceną. Powodem tego jest to, że wątek przestaje być wykonywany, gdy nie ma żadnych elementów pracy. Jeśli kiedykolwiek korzystałeś z systemu operacyjnego w czasie rzeczywistym, zadania wymagają miejsca, aby zrezygnować z procesora, aby inni mogli działać.

To, co nie jest dobrze udokumentowane, polega na tym, że podczas wysyłania performSelector: onThread: ..., jest to pętla uruchamiająca, która umieszcza wiadomość w kolejce i budzi się, aby wątek mógł ją przetworzyć. Jeśli dodasz komunikaty do pętli while, możesz to zobaczyć.

Dla naprawdę ciekawych jest przykładowy kod na githubie, na którym możesz grać z pętlami startowymi - dodaj komentarz, a ja wymienię kilka.

+0

1), ale wewnątrz wątkuProc, istnieje pętla while, więc wątek będzie zawsze zajęty? W jaki sposób NSRunLoop może go przerwać? 2) AFAIK, jest to mechanizm zapewniający, że wiele wywołań do performSelector: onThread: przeniesie pracę do tego samego wątku roboczego, prawda? – onmyway133

+0

1) przepraszam, aby nie było jasne - system operacyjny zawiesi wątek w trybie runMode: jeśli nie ma nic do przetworzenia kodu. 2) to jedna cecha systemu - ale są inne - przetwarzanie portów i timerów. Nauczysz się najbardziej, czytając dokumenty jabłek na temat CFRunloop - Wierzę, że istnieje przewodnik na ten temat. –