2012-03-03 3 views
10

Używam wielu elementów w tle za pomocą metody dispatch_async, a czasami chcę zabić to, co mam w kolejce - czy to możliwe? Na przykład ten kod jest uruchamiany w widoku, a następnie użytkownik powraca do ekranu. Wszystkie te akcje będą działały bez względu na nawigację wsteczną. Idealnie chciałabym zabić tych przedmiotów od biegania:zabijanie elementów w kolejce dispatch_async w iOS

dispatch_async(dispatch_get_global_queue(2, 0), ^{ 
     for (int i=0; i<[self.manufacturers count]; i++) { 
      NSString *manufacturerID = [[[self.manufacturers objectAtIndex:i] ManufacturerID] stringValue]; 
      [self doSync:manufacturerID withIndex:i setTimer:YES]; 
     } 
    }); 

Jeśli utworzyć kolejkę i nazwę go, a następnie zwolnić go na dealloc widoku ten nazywa się one nadal działać.

Odpowiedz

14

Nie ma wyraźnego postanowienia w kolejkach wysyłkowych do wypowiedzenia. W tym celu często testuje się lokalizację ucieczki, aby określić zakończenie. Zasadniczo byłby to semafor.

NSOperationQueue (wyższego poziomu abstrakcji, ale nadal budować przy użyciu GCD poniżej) ma wsparcie dla operacji anulowania. Na przykład, możesz utworzyć serię NSOperations i dodać je do NSOperationQueue, a następnie wysłać wiadomość -cancelAllOperations do kolejki, gdy nie będziesz jej potrzebował do ukończenia.

Wiele z wybranej architektury zależy od tego, ile z nich działa i czy mają różne wyzwalacze. Wśród implementacji, NSOperation jest prawdopodobnie "najczystszym" rozwiązaniem, ponieważ masz dowolną kolejkę, którą możesz obserwować, aby operacje zostały zakończone i możesz również anulować zaległe operacje. W następstwie skali ataków hakerskich będzie to niestabilne miejsce, w którym każdy z tych bloków będzie obserwować wewnątrz ciasnej pętli, aby ustalić, czy mają się zakończyć przedwcześnie. Jeszcze niżej byłaby zmienna globalna dla tej samej podstawowej funkcji.

Ostatecznie, nawet implementacja NSOperation wymaga testu, aby zakończyć w spójnej lokalizacji (ponieważ samo zabicie wątku może spowodować niespójności w operacjach na danych lub w przydziałach/ponownych odsłuchach).

2

Najlepszym sposobem jest utworzenie własnej kolejki współbieżnej (nie należy używać jednej z globalnych), a następnie wywołanie metody dispatch_suspend() w kolejce, aby zatrzymać przetwarzanie w niej. W tym miejscu przeczytaj: Dispatch queues: How to tell if they're running and how to stop them

Za pomocą flagi anulowania można następnie wznowić kolejkę tak, że wszystkie pozostałe bloki w zasadzie po prostu wyjść (po wykonaniu jakiegokolwiek zarządzania pamięcią, które trzeba zrobić, jak zwalnianie zasobów) po wznowieniu go jeszcze raz. Możesz także dispatch_release() kolejkę natychmiast po jej wznowieniu.