2009-08-05 11 views

Odpowiedz

17

Czy chcesz, aby wątek zatrzymywał się, dopóki inny wątek nie powie mu, aby ponownie się uruchomić? Jeśli tak, możesz użyć NSConditionLock. Blok NSConditionLock jest podobny do zmiennej warunkowej. Ma kilka podstawowych metod, lockWhenCondition i unlockWithCondition, i blokadę. Typowym zastosowaniem jest sprawdzenie, czy wątek w tle czeka na blokadę stanu z "lockWhenCondition:", a także w pierwszym planie wątku, aby ustawić warunek, który powoduje, że wątek tła się obudzi. Warunek jest prostą liczbą całkowitą, zwykle wyliczeniem.

Oto przykład:

enum { 
    kWorkTodo = 1, 
    kNoWorkTodo = 0 
} 

- (id)init { 
    if ((self = [super init])) { 
     theConditionLock = [[NSCoditionLock alloc] initWithCondition: kNoWorkTodo]; 
     workItems = [[NSMutableArray alloc] init]; 
    } 
} 

- (void)startDoingWork { 
    [NSThread detachNewThreadSelector:@selector(doBackgroundWork) toTarget:self withObject:nil]; 
} 

- (void)doBackgroundWork:(id)arg { 
    while (YES) { 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     NSArray *items = nil; 
     [theConditionLock lockWhenCondition:kWorkTodo]; // Wait until there is work to do 
     items = [NSArray arrayWithArray:workItems] 
     [workItems removeAllObjects]; 
     [theConditionLock unlockWithCondition:kNoWorkTodo]; 
     for(id item in items) { 
      // Do some work on item. 
     } 
     [pool drain]; 
    } 
} 

- (void)notifyBackgroundThreadAboutNewWork { 
    [theConditionLock lock]; 
    [workItems addObject:/* some unit of work */]; 
    [theConditionLock unlockWithCondition:kWorkTodo]; 
} 

W tym przykładzie, kiedy startDoingWork nazywa doBackgroundWork: rozpocznie się na wątku tła, ale wtedy zatrzymać, ponieważ nie ma żadnej pracy do zrobienia. Po wywołaniu funkcji notifyBackgroundThreadAboutNewWork, toBackgroundWork: uruchomi i przetworzy nową pracę, a następnie powróci do trybu uśpienia czekając na udostępnienie nowej pracy, co nastąpi przy następnym wywołaniu funkcji notifyBackgroundThreadAboutNewWork.

+1

Dziękuję bardzo za rozwiązanie. to wydaje się jak to, czego potrzebuję. –

+0

Tak więc proces koordynowania hreadów z NSlock, nie zapewnia dużej prędkości między wątkami. Próbowałem użyć metody sleep dla NSthreadand było bardzo powolne. –

+0

Czy możesz mi również powiedzieć, dlaczego pracujesz przed i po [theConditionLock unlockWithCondition: kNoWorkTodo]; również. jaka jest różnica między nslockiem a nsonditionlockiem –

0

Nie jest jasne, co chcesz zrobić. Zatrzymać wątek i wznowić tę samą funkcję w nowym wątku? (To byłoby bezcelowe - co było nie tak ze starym wątkiem?) Zatrzymać wątek i wznowić tę samą funkcję na innym istniejącym wątku?

Tak czy inaczej, nie, to niemożliwe, i nie jest to nawet dobry pomysł. Prawidłowym rozwiązaniem jest podzielenie funkcji na dwie części, a następnie użycie niektórych lub wszystkich metod pętli uruchamiania, NSTimer, performSelector… i NSPort, aby osiągnąć to, co chcesz zrobić.

Twój program będzie działał o wiele lepiej bez tej magii czarnych nici, którą sobie wyobrażasz.

+1

nie wiesz, że chcę móc zatrzymać wątek, kiedy tylko chcę. Więc rozdzielenie zadania byłoby bezcelowe. –

+2

Dlaczego chcesz to zrobić? Jeśli chcesz zatrzymać pracę, którą wykonujesz, zrób to. W przeciwnym razie prawdopodobnie zatrzymasz wątek w środku czegoś, z tą rzeczą w połowie ukończoną i pół-nie. –

+1

Czy zdajesz sobie sprawę, że zamiast pomagać ci po prostu się kłócić. Nie wiem, jak udało ci się zdobyć 10 tys. –

2

Jeśli naprawdę masz zadania, które musisz wykonać w wątku w tle, ale jedno zadanie musi zostać ukończone, zanim zostanie wykonane, polecam zajrzeć do NSOperation i NSOperationQueue. NSOperation obsługuje ustawianie bardzo złożonych zależności, a NSOperationQueue będzie obsługiwać planowanie i wykonywanie tych operacji na dowolnej liczbie wątków tła, we właściwej kolejności. Apple's documentation jest całkiem niezły, a Drew McCormack ma nice article na temat MacResearch.

Powiązane problemy