80 votes

Un thread de travail NSOperation et NSOperationQueue vs un thread principal

Je dois réaliser une série de téléchargement de base de données et les opérations d'écriture dans mon application. Je suis à l'aide de l' NSOperation et NSOperationQueue pour la même chose.

C'est le scénario de l'application:

  • Récupère tous les codes postaux à partir d'un endroit.
  • Pour chaque code postal récupérer toutes les maisons.
  • Pour chaque maison de récupérer habitant de détails

Comme dit, j'ai défini un NSOperation pour chaque tâche. Dans le premier cas (Task1), j'envoie une demande au serveur pour récupérer tous les codes postaux. Le délégué à l'intérieur de l' NSOperation recevra les données. Ces données sont ensuite écrites dans la base de données. L'opération de base de données est définie dans une classe différente. D' NSOperation classe, je fais un appel à la fonction d'écriture défini dans la base de données de la classe.

Ma question est de savoir si la base de données d'une opération d'écriture se produire dans le thread principal ou dans un thread d'arrière-plan? Comme je l'ai été de l'appeler dans un NSOperation je m'attendais à exécuter dans un thread différent (Pas MainThread) que l' NSOperation. Quelqu'un peut-il m'expliquer ce scénario tout en traitant avec des NSOperation et NSOperationQueue.

174voto

RuiAAPeres Points 14372

Ma question est de savoir si la base de données d'une opération d'écriture se produire dans les principales fil ou dans un thread d'arrière-plan?

Si vous créez un NSOperationQueue à partir de zéro, comme dans:

NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];

Il sera dans un thread d'arrière-plan:

Fonctionnement des files d'attente généralement les threads utilisés pour exécuter leurs les opérations. Dans OS X v10.6 et, plus tard, de l'exploitation des files d'utiliser le libdispatch bibliothèque (aussi connu comme Grand Central Dispatch) pour lancer l'exécution de leurs opérations. En conséquence, les opérations sont toujours exécuté sur un thread séparé, indépendamment du fait qu'ils sont désigné comme simultané ou non les opérations simultanées

Sauf si vous utilisez l' mainQueue:

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

Vous pouvez également voir le code comme ceci:

NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
[myQueue addOperationWithBlock:^{

   // Background work

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // Main thread work (UI usually)
    }];
}];

Et le PGCD version:

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
             {
              // Background work            
             dispatch_async(dispatch_get_main_queue(), ^(void)
              {
                   // Main thread work (UI usually)                          
              });
});

NSOperationQueue donne un contrôle plus précis avec ce que vous voulez faire. Vous pouvez créer des dépendances entre les deux opérations (télécharger et sauvegarder la base de données). Pour transmettre les données entre un bloc et de l'autre, vous pouvez supposer par exemple, qu'un NSData sur le serveur:

__block NSData *dataFromServer = nil;
NSBlockOperation *downloadOperation = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakDownloadOperation = downloadOperation;

[weakDownloadOperation addExecutionBlock:^{
 // Download your stuff  
 // Finally put it on the right place: 
 dataFromServer = ....
 }];

NSBlockOperation *saveToDataBaseOperation = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakSaveToDataBaseOperation = saveToDataBaseOperation;

 [weakSaveToDataBaseOperation addExecutionBlock:^{
 // Work with your NSData instance
 // Save your stuff
 }];

[saveToDataBaseOperation addDependency:downloadOperation];

[myQueue addOperation:saveToDataBaseOperation];
[myQueue addOperation:downloadOperation];

Edit: Pourquoi je suis en utilisant __weak de référence pour les Opérations, peuvent être trouvés ici. Mais en un mot est pour éviter de conserver des cycles.

16voto

serrrgi Points 396

Si vous souhaitez procéder à la base de données opération d'écriture dans le thread d'arrière-plan, vous devez créer un NSManagedObjectContext pour ce thread.

Vous pouvez créer l'arrière-plan NSManagedObjectContext dans la méthode de démarrage de votre NSOperation sous-classe.

De vérifier la Pomme de docs pour Simultanéité avec la Base de Données.

Vous pouvez également créer un NSManagedObjectContext qui exécute des demandes dans son propre thread d'arrière-plan, par la création avec NSPrivateQueueConcurrencyType et de l'exécution des requêtes à l'intérieur de son performBlock: la méthode.

11voto

ilya n. Points 6610

De NSOperationQueue

Dans iOS 4 et plus tard, l'opération files d'attente de l'utilisation de Grand Central Dispatch pour exécuter des opérations. Avant iOS 4, ils créent des threads séparés pour la non-concordance des opérations et de lancer les opérations simultanées de le thread courant.

Donc,

[NSOperationQueue mainQueue] // added operations execute on main thread
[NSOperationQueue new] // post-iOS4, guaranteed to be not the main thread

Dans votre cas, vous pourriez créer votre propre base de données "thread" subclassing NSThread et envoyer des messages avec performSelector:onThread:.

9voto

Ashok Points 2514

Le thread d'exécution de NSOperation dépend de l' NSOperationQueue où vous avez ajouté l'opération. Regardez cette déclaration dans votre code

[[NSOperationQueue mainQueue] addOperation:yourOperation]; // or any other similar add method of NSOperationQueue class

Tout ceci suppose que vous ne l'ont pas fait plus d'enfilage en main méthode de NSOperation qui est le véritable monstre où les instructions de travail que vous avez (devrait être) écrit.

Toutefois, en cas d'opérations simultanées, le scénario est différent. La file d'attente peut se frayer un thread pour chaque concurrente l'opération. Bien qu'il n'est pas guarrantteed et il dépend des ressources système vs opération de la demande de ressources à ce point dans le système. Vous pouvez contrôler la simultanéité de fonctionnement de la file d'attente par maxConcurrentOperationCount de la propriété.

EDIT -

J'ai trouvé votre question intéressante et fait un peu d'analyse et d'acquisition de moi-même. J'ai NSOperationQueue créé sur le thread principal, ce

self.queueSendMessageOperation = [[[NSOperationQueue alloc] init] autorelease];

NSLog(@"Operation queue creation. current thread = %@ \n main thread = %@", [NSThread currentThread], [NSThread mainThread]);
self.queueSendMessageOperation.maxConcurrentOperationCount = 1; // restrict concurrency

Et puis, je suis allée créer un NSOperation et de l'ajouter à l'aide addOperation. Dans la méthode principale de cette opération, lorsque j'ai vérifié pour le thread en cours,

NSLog(@"Operation obj =  %@\n current thread = %@ \n main thread = %@", self, [NSThread currentThread], [NSThread mainThread]);

il n'était pas comme thread principal. Et, a trouvé que le thread en cours d'objet n'est pas thread principal objet.

Ainsi, la coutume de la création de la file d'attente sur le thread principal (avec pas de simultanéité entre son fonctionnement) ne veut pas forcément dire que les opérations d'exécution en série sur le thread principal lui-même.

1voto

duncanwilcox Points 2923

Le résumé des documents est operations are always executed on a separate thread (post iOS 4 implique des files d’opérations sous-jacentes à GCD).

Il est trivial de vérifier qu'il fonctionne bien sur un thread non principal:

 NSLog(@"main thread? %@", [NSThread isMainThread] ? @"YES" : @"NO");
 

Lors de l'exécution dans un thread, il est facile d'utiliser GCD / libdispatch pour exécuter quelque chose sur le thread principal, qu'il s'agisse de données de base, d'interface utilisateur ou d'un autre code requis pour s'exécuter sur le thread principal:

 dispatch_async(dispatch_get_main_queue(), ^{
    // this is now running on the main thread
});
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X