2010-08-05 7 views
0

J'ai une application qui dessine des lignes sur un contexte de quartz. L'application commence à dessiner lorsque l'utilisateur déplace son doigt sur l'écran. Au moment où TouchesMoved est déclenché, je sauvegarde le contexte de quartz dans un fichier PNG (je sais que l'enregistrement d'un fichier est lent ... J'ai essayé de le faire en mémoire mais l'utilisation de la mémoire de l'application est montée en flèche, donc j'essaie le faire sur disque).iphone - le fil principal gèle pendant une demi-seconde ... pourquoi?

Le contexte est en cours d'enregistrement à cela, je le fais sur des touches déplacé

if (firstMove) // first movement after touchesbegan 
    [NSThread detachNewThreadSelector:@selector(newThreadUNDO) 
    toTarget:self 
     withObject:nil]; 
    firstMove = NO 
} 

puis je

- (void) newThreadUNDO { 

    NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init]; 

    [NSThread setThreadPriority:0.1]; 

    [NSThread sleepForTimeInterval:0.0]; 
    [self performSelectorOnMainThread:@selector(copyUNDOcontext) withObject:nil waitUntilDone:NO]; 

    [p release]; 
} 

et

- (void) copyUNDOcontext { 


    CGFloat w = board.image.size.width; 
    CGFloat h = board.image.size.height; 
    CGRect superRect = CGRectMake(0,0, w, h); 

    CGSize size = CGSizeMake(w, h); 

    UIGraphicsBeginImageContext(size); 
    CGContextRef new = UIGraphicsGetCurrentContext(); 
    // lineLayer is the layer context I need to save 
    CGContextDrawLayerInRect(new, superRect, lineLayer); 
    UIImage *imagem = UIGraphicsGetImageFromCurrentImageContext(); 

    [self saveTempImage:imagem :@"UNDO.png"]; 
    UIGraphicsEndImageContext(); 

} 

Le problème est: que Dès que l'utilisateur commence à se déplacer, le nouveau thread est déclenché, mais même ce nouveau thread étant de faible priorité, le thread principal reste figé pour environ une demi-seconde (probablement pendant l'enregistrement du fichier).

Pourquoi est-ce?

Comment puis-je résoudre ce problème?

merci.

Répondre

1

Avez-vous essayé:

performSelector:onThread:withObject:waitUntilDone: 

Avec waitUntilDone réglé sur NO. Si je me souviens que l'exécution correcte du sélecteur sur le fil principal traite toujours le sélecteur dans la boucle d'exécution principale de l'application. Je peux me tromper. J'utilise GCD depuis un certain temps maintenant.

Si vous essayez ceci, je crois que vous aurez besoin de mettre le pool autorelease dans la fonction, car il servira de point d'entrée et de sortie du thread.

+0

merci! fonctionne comme un charme! – SpaceDog

+0

Content que cela fonctionne. Dans le futur, vous voudrez peut-être créer un pool de threads. De cette façon, vous n'allouez pas un pool de versions et threadez plusieurs fois. Cependant, iOS peut très bien avoir un pool de threads en arrière-plan qui renvoie les threads disponibles (ou globaux) aux allocations. Je dirais plus sur iOS 4 que sur GCD. À tout le moins, vous économiserez quelques cycles de cpu. Gardez à l'esprit que toucher du cacao d'un autre fil peut devenir une situation inconfortable. –

1

D'abord, une méthode nommée saveTempImage:: doit être déconseillée. Faites-le saveTempImage:fileName: ou quelque chose.

Votre estimation est probablement bonne; enregistrer le fichier est probablement d'où vient la pause. Pourrait aussi être le rendu lui-même, si compliqué, mais ne ressemble pas à ça. Toutefois, le fait de deviner est généralement un moyen improductif d'analyser les problèmes de performances. Utilisez les outils fournis. L'instrument CPU Sampler pourrait vous dire ce qui se passe réellement.

Pour réparer? D'abord confirmer le problème. Si c'est le fichier I/O, déplacez-le du thread principal (je n'ai pas regardé la documentation de UIImage pour savoir s'il est sûr pour les threads dans un tel contexte).

Questions connexes