2009-11-21 11 views
2

J'ai un NSOperation qui télécharge des données en utilisant NSURLConnection, il semble un peu comme ceci:Annulation de l'opération avec connexion à l'intérieur

.... 
- (void)main 
{ 
.... 
    while (!self.isCancelled && !self.isLoaded) 
    { 
     [NSRunloop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NDate distantFutute]]; 
    } 
.... 
} 

Le problème est que de temps à connexion se bloque de temps et comme il n'y a pas d'autres sources mise à feu , la boucle continue de tourner pour toujours, ne laissant aucune chance d'annuler l'opération. Comme il y a une limite pour 1 opération dans ma file d'attente, tout est bloqué.

La question est quelle serait la meilleure solution à ce problème.

  1. Au lieu de remoteFuture, utilisez une période plus courte d'une demi-seconde. (Va probablement manger des cycles de cpu supplémentaires)
  2. Essayez de stocker une référence au thread en cours d'exécution dans la boucle d'exécution ivar et tickle via un sélecteur sur le thread dans la méthode d'annulation de l'opération. (Peut entraîner une situation où nous mettons en file d'attente un sélecteur sur une boucle d'exécution qui a déjà quitté et ne fonctionnera plus, ce qui entraîne une fuite autant que je sache)

Ou peut-être existe-t-il un autre moyen?

Répondre

3

Voici une approche hybride:

  • Exécutez la boucle d'exécution le plus longtemps que vous êtes prêt à attendre que les données à charger (beforeDate:[NSDate dateWithTimeIntervalSinceNow:kConnectionMaxWaitSeconds]).
  • Créez une source de boucle d'exécution de version 0 (CFRunLoopSourceCreate) et ajoutez-la à la boucle d'exécution avant de commencer à attendre.
  • Avoir la méthode -cancel signaler cette source (CFRunLoopSourceSignal) et réveiller (CFRunLoopWakeUp) la boucle d'exécution.
+0

Approche très intéressante. J'essaierai certainement cela, merci. – stackzerad

+0

Juste une question de plus. Qu'est-ce qui crée et signale la source? pourquoi je ne peux pas simplement appeler CFRunLoopWakeUp? – stackzerad

+0

Peut-être que c'est inutile. Essayez d'utiliser simplement 'CFRunLoopWakeUp()' et voyez. –