2011-08-01 6 views
1

Je suis relativement nouveau à l'objectif-c, et ayant un problème de synchronisation de thread. J'essaye de renvoyer une image à l'utilisateur (par l'URL d'image fournie par l'utilisateur). Je lance le téléchargement d'image dans un fil séparé, avec la fonction de filetage déclarée et définie dans ma classe actuelle. Le problème est que le fil est CHAISE, ma fonctionnalité de téléchargement de l'image ne fonctionne pas (c.-à aucune des méthodes NSURLConnection OBTIENNENT appeléMultithreading issue

Ma fonction de la classe pour initier le fil et le téléchargement de l'image est la suivante:.

- (NSMutableData*)download:(NSString*)strURL 
{ 
    self.strURLData=strURL; 
    [NSThread detachNewThreadSelector:@selector(threadMethod:) toTarget:[ICacheImageDownloadMgr class] withObject:self]; 
    //Here ICacheImageDownloadMgr is my current class 
    while(!bCompletionFlag) 
    { 
     if(bCompletionFlag)//bCompletionFlag is set to TRUE in NSURLConnection::connectionDidFinishLoading method after successful image download 
     { 
      return currentData; 
     } 
    } 
} 

mon seul motif est ici pour revenir « CurrentData » après le processus de téléchargement d'image terminée, l'utilisateur et la méthode de fil déclaré dans ma classe actuelle (c.-à-ICacheImageDownloadMgr) est la suivante:.

+ (void) threadMethod:(ICacheImageDownloadMgr*)param 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; 

    if(param.currentData) 
    { 
     [param.currentData release]; 
     param.currentData=nil; 
    } 
    param.currentData = [[NSMutableData alloc]initWithLength:0]; 

    NSURL *myURL = [[NSURL alloc] initWithString:param.strURLData]; 
    NSURLRequest *URLRequest = [NSURLRequest requestWithURL: myURL]; 
    param.urlcon = [[NSURLConnection alloc]initWithRequest:URLRequest delegate:self startImmediately:YES]; 
    [myURL release]; 

    param.dataLock = [[NSLock alloc]init]; 

    while(!param.bCompletionFlag) 
    { 
     if([param.dataLock tryLock]) 
     { 
      if(param.bCompletionFlag)//bCompletionFlag is set to TRUE in NSURLConnection::connectionDidFinishLoading method after successful image download, along with NSLock unlock call 
      { 
       break; 
      } 
     } 
    } 

    [pool release]; 

} 

S'il vous plaît laissez-moi savoir ce que je fais mal ici? Il semble que mes deux threads ici sont en blocage et c'est pourquoi mes méthodes NSURLConnection ne sont pas appelées. Encore une fois, comme indiqué précédemment, mon seul but est de retourner "currentData" à l'utilisateur.

Merci,

Répondre

1

Dans votre code:

param.urlcon = [[NSURLConnection alloc]initWithRequest:URLRequest delegate:self startImmediately:YES];

Commencera une connexion asynchrone qui repose sur des méthodes de délégués pour vous permettre de gérer le transfert en cours. Sur une autre note, puisque vous commencez un fil pour vos demandes, vous pouvez vous simplifier la vie et les rendre synchrones (et en fait, vous ne pouvez pas dire ce qui s'y passe). Je pense que c'est ce que vous visiez en premier lieu), de sorte que vous n'avez pas à traiter avec le protocole des délégués. Vous pouvez utiliser le

+ sendSynchronousRequest:returningResponse:error: 
méthode

pour que, par exemple .:

[NSURLConnection sendSynchronousRequest:URLRequest returningResponse:&yourResponse error:&yourError]; 
+0

merci pour vos conseils sur l'utilisation de sendSynchronousRequest. C'est exactement ce que j'avais l'intention de faire. Mon code fonctionne maintenant. Cependant, je ne suis toujours pas capable de comprendre pourquoi mon implémentation des méthodes de délégué NSURLConnection (comme didReceiveResponse, didReceiveData, et connectionDidFinishLoading) n'était pas appelée dans mon code? Je suppose que, comme mentionné par tia, la boucle while dans mon threading principal bloquait l'application elle-même. – XMarshall

+0

Vous devriez avoir créé une boucle d'exécution dans votre thread je pense ... dans votre thread vous entrez un moment qui ne permet pas la réponse à traiter je pense ... vous pouvez lire ceci: http: //developer.apple. com/Bibliothèque/ios/# documentation/Cocoa/Conceptuel/Multithreading/RunLoopManagement/RunLoopManagement.html – sergio

0

Quelques choses

  1. Utilisation NSOperation au lieu de fil, encore mieux jeter un oeil à ASIHttpRequest.
  2. Démarrage d'un nouveau thread, puis en attendant qu'il se termine est un gaspillage d'un thread. Ce que vous devez faire, c'est de faire faire la gestion des requêtes dans un thread, puis de le récupérer quand il aura fini avec les données.
1

Désolé de le dire mais c'est faux à trop d'endroits.

  1. Vous saturez fil conducteur avec boucle while serré dans download:, ce qui est pas bon parce que l'autre thread aura moins de temps CPU au travail.
  2. La boucle while dans download: bloque pratiquement thread principal, ce qui rendra votre interface utilisateur ne répond pas jusqu'à ce que la boucle soit terminée.
  3. Il n'y a aucune garantie que la boucle finira jamais.
  4. NSURLConnection Le démarrage est déjà asynchrone, vous n'avez donc pas besoin de thread.
  5. Les propriétés ICacheImageDownloadMgr est retain ou assign? Je ne pense pas que vous avez fait la gestion de la mémoire correctement, et cela entraînera des fuites de mémoire ou un accident.
0

Ce n'est pas la façon de travailler avec NSURLConnection. Comme sergio mentionné, NSURLConnection fonctionne avec la méthode délégués qui renvoie les réponses et les données, que vous devez collecter. NSURLConnection crée lui-même un thread d'arrière-plan pour son opération asynchrone et renvoie ses méthodes déléguées au thread principal, vous n'avez donc pas besoin de créer vous-même un thread d'arrière-plan. En outre, si vous attendez un indicateur indiquant que la connexion est terminée dans une boucle while, il n'y a aucun avantage de fond. De plus, votre application va balancer la balle jusqu'à ce que la connexion soit terminée, puisque vous ne retournez pas le contrôle à la boucle d'exécution.