2009-10-03 6 views
6

Je travaille avec un code qui fait un tas de fonctionnement asynchrone avec différents rappels; Snow Leopard a rendu cela incroyablement facile avec des blocs et des GCD.Quelle est la légèreté de NSOperationQueue sur Snow Leopard?

J'appelle NSTask d'un NSBlockOperation comme ceci:

[self.queue addOperationWithBlock:^{ 
    NSTask *task = [NSTask new]; 
    NSPipe *newPipe = [NSPipe new]; 
    NSFileHandle *readHandle = [newPipe fileHandleForReading]; 
    NSData *inData = nil; 
    [task setLaunchPath:path]; 
    [task setArguments:arguments]; 
    [task launch]; 

    while ((inData = [readHandle availableData]) && [inData length]) { 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      // callback 
     }]; 
    } 

    [task waitUntilExit]; 
}]; 

Cette approche fonctionne parfaitement. C'est magique, tant que mes rappels traitent la concurrence correctement. Maintenant, je veux être en mesure de fusionner certains de ces appels; ceci est à l'intérieur de la méthode "refresh" d'un objet modèle et peut prendre beaucoup de temps à se terminer. Avoir l'utilisateur sur le bouton d'actualisation ne doit pas bloquer la machine et tout ça.

Je peux voir un dilemme de mise en œuvre ici. Je peux créer tout un tas de files d'attente (une par type d'appel) et définir leur nombre d'opérations simultanées sur 1, puis appeler -cancelAllOperations chaque fois qu'il est temps d'effectuer un nouvel appel.

Alternativement, je pourrais faire un peu plus de comptabilité manuelle sur laquelle les appels sont en train de se passer et gérer une seule file par objet de modèle (comme je le fais) ou je pourrais aller plus loin et utiliser une file d'attente globale.

Quelle est la taille de NSOperationQueue? Est-ce que créer beaucoup de files d'attente est une mauvaise décision d'architecture? Existe-t-il un meilleur moyen de fusionner ces tâches?

+2

FYI, vous fuyez votre NSTask et votre NSPipe. + new est équivalent à + alloc/-init, ce qui signifie que vous êtes responsable de les libérer ... ce que vous ne faites jamais (dans votre code ci-dessus). (à moins, bien sûr, que vous utilisiez GC) –

+1

C'est un programme Snow Leopard uniquement. J'espère que votre tout nouveau code Snow-Leopard sera récupéré. :-D –

Répondre

8

Si vous êtes préoccupé par les performances, ne devinez pas: mesurez puis corrigez les goulots d'étranglement que vous trouvez. L'ajout de files d'attente est simple. essayez-le et voyez ce que les instruments vous disent de l'effet sur la performance.

La principale raison de la création de plusieurs files d'attente est que vous ayez des raisons de vouloir les démarrer et les arrêter. Si vous voulez juste obtenir les avantages de libdispatch, vous pouvez obtenir cela en ajoutant simplement des opérations à la file d'attente principale. Utilisez simplement autant de files d'attente d'opérations que vous le souhaitez.

0

Ils sont là pour séparer les parties logiques de votre programme. Je ne pense pas que vous devriez être trop préoccupé par la performance tant que vous n'allouez pas des centaines de files d'attente par seconde.

+0

Site web? Qu'est-ce que cela a à voir avec les sites Web? –

+0

Merci, il est encore trop tôt le matin. :) –

1

Vous pouvez ajouter plusieurs blocs à une opération NSBlockOperation qui sera exécutée simultanément et qui peut être annulée par en annulant l'opération conteneur. Tant que vos tâches individuelles ne doivent pas être sérialisées, cela peut fonctionner.

+0

Ce n'est pas ce que disent les docs: "La classe NSBlockOperation est une sous-classe concrète de NSOperation qui gère l'exécution simultanée d'un ou plusieurs blocs." http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/NSBlockOperation_class/Reference/Reference.html –

+0

Jim, vous avez absolument raison. Réponse mise à jour Merci. –

Questions connexes