2013-08-15 1 views
15

Je souhaite simuler une communication avec un serveur. Comme le serveur distant aura des retards que je veux utiliser un fil d'arrière-plan qui a sur elleNSThread sleepfortimeinterval bloque le thread principal

[NSThread sleepForTimeInterval:timeoutTillAnswer]; 

Le fil est créé avec NSThread sous classage et a commencé ... Cependant, je remarque que sleepForTimeInterval bloque le thread principal. .. Pourquoi??? NSThread n'est-il pas un backgroundThread par défaut?

Voici comment le fil est créé:

self.botThread = [[PSBotThread alloc] init]; 
    [self.botThread start]; 

Plus d'info: Ce est le fil conducteur bot subclas

- (void)main 
{ 
    @autoreleasepool { 
     self.gManager = [[PSGameManager alloc] init]; 
     self.comManager = [[PSComManager alloc] init]; 
     self.bot = [[PSBotPlayer alloc] initWithName:@"Botus" andXP:[NSNumber numberWithInteger:1500]]; 
     self.gManager.localPlayer = self.bot; 
     self.gManager.comDelegate = self.comManager; 
     self.gManager.tillTheEndGame = NO; 
     self.gManager.localDelegate = self.bot; 
     self.comManager.gameManDelegate = self.gManager; 
     self.comManager.isBackgroundThread = YES; 
     self.comManager.logginEnabled = NO; 
     self.gManager.logginEnabled = NO; 
     self.bot.gameDelegate = self.gManager; 
     BOOL isAlive = YES; 
     // set up a run loop 
     NSRunLoop *runloop = [NSRunLoop currentRunLoop]; 
     [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 
     [self.gManager beginGameSP]; 
     while (isAlive) { // 'isAlive' is a variable that is used to control the thread existence... 
      [runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
     } 



    } 
} 

- (void)messageForBot:(NSData *)msg 
{ 
    [self.comManager didReceiveMessage:msg]; 
} 

Je veux appeler "messageForBot" du fil conducteur ... aussi le thread d'arrière-plan devrait appeler une méthode sur le thread principal pour communiquer .. Le sommeil pour intervail temps dans l'intérieur de l'objet gManager ....

+0

Montrez comment vous créez le fil , ce qu'il fait et quand vous appelez 'sleepForTimeInterval:' (qui retarde le thread en cours à le moment où ça s'appelle). – Wain

+0

Voilà comment je crée le fil ... [self.botThread start]; ... Cela appelle la méthode principale PSBotThread de la sous-classe NSThread ... – user1028028

+0

Mais que fait-il? Où est le 'sleepForTimeInterval'? – Wain

Répondre

22

Il bloque quel que soit le thread sur lequel sleepForTimeInterval est en cours d'exécution. Lancez-le sur un autre thread pour simuler votre retard de serveur comme ceci:

dispatch_queue_t serverDelaySimulationThread = dispatch_queue_create("com.xxx.serverDelay", nil); 
dispatch_async(serverDelaySimulationThread, ^{ 
    [NSThread sleepForTimeInterval:10.0]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
      //Your server communication code here 
    }); 
}); 
+0

Je ne pense pas que cela fonctionnera ... peut-être que le thread creatoin devrait être dans le dispatch_async? – user1028028

+0

Je l'utilise et ça marche bien. J'ai fait la même chose pour simuler la latence du réseau. Le dispatch_queue_create a déjà créé un autre thread. SleepForTimeInterval dans dispatch_async provoquera la mise en veille de ce thread. – John

+0

Cela marche pour moi aussi :-) – Donald

1

Essayez de créer une méthode dans votre classe thread appelé sleepThread

-(void)sleepThread 
{ 
    [NSThread sleepForTimeInterval:timeoutTillAnswer]; 
} 

Alors pour le rendre le sommeil de votre fil conducteur

[self.botThread performSelector:@selector(sleepThread) onThread:self.botThread withObject:nil waitUntilDone:NO]; 

Pour envoyer la mise à jour à votre thread principal à partir de votre thread bot.

dispatch_async(dispatch_get_main_queue(), ^{ 
    [MainClass somethinghasUpdated]; 
}); 

Side Note

Pour créer le runloop Je pense que tout ce que vous devez faire est

// Run the Current RunLoop 
[[NSRunLoop currentRunLoop] run]; 
+0

Je n'ai pas besoin de le faire dormir depuis le fil principal ...il devrait se mettre en veille après avoir reçu un message du thread principal – user1028028

+0

Ok, donc vous voulez qu'il dorme dans la méthode - (void) messageForBot: (NSData *) msg? – sbarow

+0

NON, cette méthode appellera une autre sur l'un des objets internes créés dans la méthode principale ... là j'en ai besoin pour dormir ... sans bloquer l'interface utilisateur comme il le fait maintenant – user1028028

0

Swift:

let nonBlockingQueue: dispatch_queue_t = dispatch_queue_create("nonBlockingQueue", DISPATCH_QUEUE_CONCURRENT) 
dispatch_async(nonBlockingQueue) { 
    NSThread.sleepForTimeInterval(1.0) 
    dispatch_async(dispatch_get_main_queue(), { 
     // do your stuff here 
    }) 
} 
Questions connexes