2017-04-05 47 views
8

Nurkuję trochę głębiej w współbieżność i dużo czytałem o GCD i NSOperation. Jednak wiele postów, takich jak canonic answer on SO ma kilka lat.2017/Swift 3.1 - GCD kontra NSOperation

Wydawało mi się, że NSOperation główne zalety kiedyś, kosztem pewnej wydajności:

  • „do zrobienia” na ogół więcej niż zwykłą wysłania jako abstrakcji najwyższy poziom (zbudowany na szczycie GCD)
  • dokonać manipulacji zadania (anulowanie, etc.) dużo łatwiej
  • łatwo skonfigurować zależności między zadaniami

danym NWD za DispatchWorkItem & blok anulowanie/DispatchGroup/qos w szczególności, jest tam naprawdę zachęta (koszt wydajność wise) używać NSOperation już dla współbieżności oprócz przypadków, w których trzeba być w stanie anulować zadanie, kiedy to rozpoczęła się wykonaniem lub zapytać o stan zadania?

Apple wydaje się kładzie większy nacisk na GCD, przynajmniej w ich WWDC (przyznał, że jest nowszy niż NSOperation).

Odpowiedz

4

Widzę, że każdy nadal ma swój własny cel. Niedawno odświeżyłem rozmowę o WWDC z 2015 roku (Advanced NSOperations) i widzę tu dwie główne kwestie.

Run Time Interakcje & użytkownika

Z rozmowy:

NSOperations prowadzonym na trochę dłużej niż można się spodziewać blok uruchomić, więc bloki zwykle potrwać kilka nanosekund, może co najwyżej milisekundę do wykonania.

NSOperations, z drugiej strony, może być znacznie dłuższy, bo wszędzie od kilku milisekund do nawet kilku minut

Przykład mówią o jest w aplikacji WWDC, gdzie istnieje NSOperation że ma zależność od posiadania zalogowanego użytkownika. Zależność NSOperation przedstawia kontroler widoku logowania i czeka na uwierzytelnienie użytkownika. Po zakończeniu, NSOperation kończy się i NSOperationQueue wznawia pracę. Nie sądzę, że chciałbyś użyć GCD w tym scenariuszu.

instacji

Od NSOperations są tylko klasy, podklasy można je zdobyć więcej ponownego wykorzystania z nich. Nie jest to możliwe w przypadku GCD.

Przykład: (Korzystanie z logowania scenariusz WWDC z góry)

Masz wiele NSOperations w swojej bazie kodu, które są związane z interakcji z użytkownikiem, który wymaga, aby były uwierzytelnione. (W tym przykładzie polubisz film). Możesz rozszerzyć NSOperation, aby utworzyć AuthenticatedOperation, a następnie wszystkie te NSOperations rozszerzyć tę nową klasę.

1

pierwsze, NSOperationQueue pozwalają enqueue operacji, że jest jakiś asynchronicznych operacji o start metody, metody cancel i kilka właściwości obserwowalnych, podczas gdy w kolejce wysyłki można złożyć blok lub funkcja zamknięcia do kolejki wysyłkowej, która zostanie następnie wykonana.

"Operacja" jest semantycznie fundamentalnie inna niż blok (lub zamknięcie, funkcja). Operacja ma podstawowe zadanie asynchroniczne, podczas gdy blok (zamknięcie lub funkcje) jest właśnie taki.

Co zbliża się do NSOperation, choć jest asynchroniczny funkcji, np:

func asyncTask(param: Param, completion: (T?, Error?) ->()) 

Teraz Futures możemy zdefiniować tę samą funkcję asynchroniczną jak:

func asyncTask(param: Param) -> Future<T> 

dzięki czemu takie asynchroniczne funkcje są bardzo przydatne.

Ponieważ kontrakty mają funkcje COMBINATOR jak map i flatMap i tak dalej, możemy dość łatwo „emulować” na „zależność” cechę NSOperation, tylko w mocniejszym, bardziej zwięzły i bardziej zrozumiały sposób.

Możemy również zaimplementować jakąś NSOperationQueue z kilku linii kodu opartych wyłącznie na GCD, powiedzieć „TaskQueue” oraz z zasadniczo takie same funkcje, takie jak „maxConcurrentTasks” i można go używać do enqueue funkcje zadania (nie operacje), w jeszcze bardziej potężny, bardziej zwięzły i bardziej zrozumiały sposób, jak również. ;)

Aby uzyskać operację do anulowania, należy utworzyć podklasę o nazwie NSOperation - podczas gdy można utworzyć funkcję asynchroniczną "ad-hod" - wbudowaną.

Ponadto, od anulowanie jest niezależną koncepcją, możemy założyć, że istnieje pewna biblioteka, której implementacja jest oparta wyłącznie na GCD, która rozwiązuje ten problem w, uhm, zwykły sposób;) To może wyglądać tak :

self.cancellationRequest = CancellationRequest() 
self.asyncTask(param: param, cancellationToken: cr.token).map { result in 
    ... 
} 

i później:

override func viewWillDisappear(_ animated: animated) { 
    super.viewWillDisappear(animated) 
    self.cancellationRequest.cancel() 
} 

więc IMHO nie ma naprawdę żadnego powodu, aby użyć przylegający NSOperation i NSOperationQueue, i nie ma powodu, dla podklasy więcej NSOperation, co jest dość skomplikowane i zaskakujące trudne, chyba że nie dbasz o wyścigi danych.