Estou aprendendo sobre programação simultânea para iOS. Até agora eu li sobre NSOperation
/NSOperationQueue
e GCD
. Quais são as razões para usar NSOperationQueue
repetidamente GCD
e vice-versa?
Soa como ambos GCD
e NSOperationQueue
abstrai a criação explícita NSThreads
do usuário. No entanto, a relação entre as duas abordagens não está clara para mim, portanto qualquer feedback deve ser apreciado!
ios
concurrency
grand-central-dispatch
nsoperation
nsoperationqueue
Domingo segunda-feira
fonte
fonte
Respostas:
GCD
é uma API baseada em C de baixo nível que permite o uso muito simples de um modelo de simultaneidade baseado em tarefas.NSOperation
eNSOperationQueue
são classes Objective-C que fazem uma coisa semelhante.NSOperation
foi introduzido primeiro, mas a partir do 10.5 e iOS 2 ,NSOperationQueue
e os amigos são implementados internamente usandoGCD
.Em geral, você deve usar o nível mais alto de abstração que atenda às suas necessidades. Isso significa que você geralmente deve usar em
NSOperationQueue
vez deGCD
, a menos que precise fazer algo queNSOperationQueue
não é compatível.Observe que
NSOperationQueue
não é uma versão "simplificada" do GCD; de fato, há muitas coisas que você pode fazer com muita simplicidade eNSOperationQueue
que exigem muito trabalho com puraGCD
. (Exemplos: filas com restrição de largura de banda que executam apenas operações N de cada vez; estabelecendo dependências entre operações. Muito simples comNSOperation
, muito difícil comGCD
.) A Apple fez o trabalho duro de alavancar o GCD para criar uma API agradável e amigável para objetosNSOperation
. Aproveite o trabalho deles, a menos que você tenha um motivo para não fazê-lo.Advertência : Por outro lado, se você realmente precisa enviar um bloco e não precisa de nenhuma das funcionalidades adicionais que
NSOperationQueue
fornecem, não há nada de errado em usar o GCD. Apenas certifique-se de que é a ferramenta certa para o trabalho.fonte
De acordo com a minha resposta a uma pergunta relacionada , vou discordar de BJ e sugerir que você examine primeiro o GCD sobre NSOperation / NSOperationQueue, a menos que este último forneça algo que o GCD não precisa.
Antes do GCD, eu usava muitos NSOperations / NSOperationQueues em meus aplicativos para gerenciar a simultaneidade. No entanto, desde que comecei a usar o GCD regularmente, substituí quase completamente o NSOperations e o NSOperationQueues por blocos e filas de despacho. Isso veio da maneira como utilizei as duas tecnologias na prática e do perfil que realizei nelas.
Primeiro, há uma quantidade não trivial de sobrecarga ao usar NSOperations e NSOperationQueues. Esses são objetos de cacau e precisam ser alocados e desalocados. Em um aplicativo iOS que escrevi que renderiza uma cena 3D a 60 FPS, eu estava usando NSOperations para encapsular cada quadro renderizado. Quando criei um perfil disso, a criação e o detalhamento dessas operações de NSO foram responsáveis por uma parte significativa dos ciclos da CPU no aplicativo em execução e estavam atrasando as coisas. Substituí-os por blocos simples e uma fila serial do GCD, e essa sobrecarga desapareceu, levando a um desempenho notavelmente melhor na renderização. Este não foi o único lugar em que notei sobrecarga ao usar NSOperations, e já vi isso no Mac e no iOS.
Segundo, há uma elegância ao código de despacho baseado em bloco que é difícil de combinar ao usar o NSOperations. É incrivelmente conveniente agrupar algumas linhas de código em um bloco e enviá-lo para uma fila serial ou simultânea, onde a criação de um NSOperation ou NSInvocationOperation personalizado para fazer isso exige muito mais código de suporte. Eu sei que você pode usar um NSBlockOperation, mas também pode estar enviando algo para o GCD. Embrulhar esse código em blocos alinhados com o processamento relacionado em seu aplicativo leva, em minha opinião, a uma melhor organização de código do que ter métodos separados ou NSOperations personalizadas que encapsulam essas tarefas.
NSOperations e NSOperationQueues ainda têm usos muito bons. O GCD não tem um conceito real de dependências, onde NSOperationQueues pode configurar gráficos de dependência bastante complexos. Eu uso NSOperationQueues para isso em alguns casos.
No geral, embora eu costumo advogar o uso do mais alto nível de abstração que realiza a tarefa, este é um caso em que defendo a API de nível mais baixo da GCD. Entre os desenvolvedores de iOS e Mac com quem conversamos sobre isso, a grande maioria escolhe usar o GCD em vez de NSOperations, a menos que eles tenham como alvo versões de SO sem suporte para ele (antes do iOS 4.0 e do Snow Leopard).
fonte
GCD
é uma API baseada em C de baixo nível.NSOperation
eNSOperationQueue
são classes Objective-C.NSOperationQueue
é o wrapper C objetivoGCD
. Se você estiver usando o NSOperation, estará implicitamente usando o Grand Central Dispatch.Vantagem de GCD sobre NSOperation:
i. implementação
Para
GCD
implementação é muito leveNSOperationQueue
é complexo e pesadoVantagens de NSOperation sobre GCD:
Eu. Controle Na operação,
você pode pausar, cancelar, retomar uma
NSOperation
ii. Dependências que
você pode configurar uma dependência entre duas
NSOperations
operações não serão iniciadas até que todas as suas dependências retornem verdadeiras para concluídas.
iii. State of Operation
pode monitorar o estado de uma operação ou fila de operações. pronto, executando ou finalizado
iv. Número máximo de operações,
você pode especificar o número máximo de operações na fila que podem ser executadas simultaneamente
Quando procurar
GCD
ouNSOperation
quando desejar mais controle sobre o uso da fila (todos mencionados acima)
NSOperation
e para casos simples em que você deseja menos custos indiretos (você só quer fazer algum trabalho "em segundo plano" com muito pouco trabalho adicional)GCD
ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/ http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html http : //nshipster.com/nsoperation/
fonte
Outro motivo para preferir a NSOperation ao GCD é o mecanismo de cancelamento da NSOperation. Por exemplo, um aplicativo como 500px que mostra dezenas de fotos, use NSOperation, podemos cancelar solicitações de células de imagem invisíveis ao rolar a exibição de tabela ou exibição de coleção, isso pode melhorar muito o desempenho do aplicativo e reduzir o consumo de memória. O GCD não pode suportar isso facilmente.
Também com NSOperation, o KVO pode ser possível.
Aqui está um artigo de Eschaton que vale a pena ler.
fonte
NSOperation
para isso, comoNSURLSessionTask.cancel
eNSURLSession.invalidateAndCancel
fornecer essa funcionalidade. Em geral,NSURLSession
proporciona algumas das funcionalidades de umNSOperationQueue
, comoNSURLSessionTask
fornece alguma da funcionalidade de umNSOperation
O GCD é realmente de nível inferior ao NSOperationQueue, sua principal vantagem é que sua implementação é muito leve e focada em algoritmos e desempenho sem bloqueios.
O NSOperationQueue fornece recursos que não estão disponíveis no GCD, mas eles têm um custo não trivial, a implementação do NSOperationQueue é complexa e pesada, envolve muito bloqueio e usa o GCD internamente apenas de uma maneira muito mínima.
Se você precisar dos recursos fornecidos pelo NSOperationQueue, use-o de qualquer maneira, mas se o GCD for suficiente para suas necessidades, eu recomendaria usá-lo diretamente para obter melhor desempenho, reduzir significativamente o custo de CPU e energia e mais flexibilidade.
fonte
O NSQueueOperations e o GCD permitem executar tarefas de computação pesada em segundo plano em threads separados, liberando o passo principal do aplicativo de interface do usuário.
Bem, com base na postagem anterior, vemos que o NSOperations tem addDependency para que você possa enfileirar sua operação uma após a outra sequencialmente.
Mas também li sobre as filas seriais do GCD que você pode criar para executar suas operações na fila usando dispatch_queue_create. Isso permitirá executar um conjunto de operações, uma após a outra, de maneira seqüencial.
Vantagens do NSQueueOperation sobre o GCD:
Ele permite adicionar dependência e remover a dependência para que, em uma transação, você possa executar sequencialmente usando dependência e em outras transações simultaneamente, enquanto o GCD não permite executar dessa maneira.
É fácil cancelar uma operação se estiver na fila e pode ser interrompida se estiver em execução.
Você pode definir o número máximo de operações simultâneas.
Você pode suspender a operação em que estão na fila
Você pode encontrar quantas operações pendentes existem na fila.
fonte
O GCD é muito fácil de usar - se você deseja fazer algo em segundo plano, basta escrever o código e enviá-lo para uma fila de segundo plano. Fazer o mesmo com o NSOperation é muito trabalho adicional.
A vantagem do NSOperation é que (a) você tem um objeto real para o qual pode enviar mensagens e (b) que pode cancelar um NSOperation. Isso não é trivial. Você precisa subclassificar NSOperation, precisa escrever seu código corretamente para que o cancelamento e o término correto de uma tarefa funcionem corretamente. Portanto, para coisas simples, você usa o GCD e, para coisas mais complicadas, cria uma subclasse de NSOperation. (Existem subclasses NSInvocationOperation e NSBlockOperation, mas tudo o que fazem é mais fácil com o GCD, portanto, não há um bom motivo para usá-las).
fonte
Bem, as NSOperations são simplesmente uma API criada sobre o Grand Central Dispatch. Então, quando você estiver usando NSOperations, ainda estará usando o Grand Central Dispatch. É que as NSOperations oferecem alguns recursos interessantes que você pode gostar. Você pode tornar algumas operações dependentes de outras operações, reordenar filas depois de suprimir itens e outras coisas assim. De fato, o ImageGrabber já está usando NSOperations e filas de operações! O ASIHTTPRequest os utiliza sob o capô, e você pode configurar a fila de operações que ele usa para um comportamento diferente, se desejar. Então, qual você deve usar? O que fizer sentido para o seu aplicativo. Para este aplicativo, é bastante simples, então usamos o Grand Central Dispatch diretamente, sem a necessidade dos recursos sofisticados do NSOperation. Mas se você precisar deles para o seu aplicativo, fique à vontade para usá-lo!
fonte