2010-09-23 13 views
0

voici ce que je veux:objectif-c/iphone: comment définir que toutes les méthodes d'un objet vont s'exécuter sur un thread spécifique?

créer un objet qui «vit» dans son propre thread, toutes les méthodes doivent être exécutées dans ce thread.

i.e.:

// i'm in the main thread 
MyClass *myObject = [ [MyClass alloc] init ]; // it creates its own thread 
[myObject method1]; // should execute the method1 in myObject's thread 
[myObject method2]; // should execute the method2 in myObject's thread 
[myobject release]; // should deallocate everything that is used for myObject and remove myObject's thread 

j'ai lu sur les threads et runloops. J'ai créé un nouveau thread sur la méthode init, son point d'entrée est la méthode runloop. Le runloopMethod juste définir les choses les plus élémentaires nécessaires pour exécuter un NSRunLoop et l'exécute.

aThread = [[NSThread alloc] initWithTarget:self selector:@selector(runloopMethod) object:nil]; 
[aThread start]; 

il a bien fonctionné, mais quand j'appelle une méthode (par exemple: [myObject method1];) du fil conducteur, il ne fonctionne sur le thread principal, comment il ?, que je connais bien, parce que method1 effectue plusieurs opérations qui bloque l'interface utilisateur. Qu'est-ce que je l'ai fait est de rediriger l'appel de cette façon:

// on MyClass.m 
-(void) method1 { 
    if ([NSThread currentThread] != aThread) { 
     [self performSelector:@selector(method1) onThread:aThread withObject:nil waitUntilDone:YES]; 
    }else { 
     // do my stuff 
    } 

il travaille, mais cette façon me limite, j'ai aussi quelques questions pour vous:

je me suis rendu compte que si je suis X-thread et appeler une méthode d'un objet, il sera exécuté dans X-thread. Je pense que l'appel de la méthode sera ajouté (pas sûr si c'est le mot) au runloop du X-thread. droite?

Y at-il un moyen de définir cela: tout appel aux méthodes de mon objet sera exécuté sur le thread de l'objet? (sans faire tout ça).

aussi, est-ce la bonne façon pour ce que je fais? La méthode 1, la méthode 2, etc. sont la version de synchronisation de mes fonctions. Elles bloquent donc l'interface utilisateur. que 'pourquoi je suppose avoir un autre fil est la façon.

merci de votre lecture !.

btw. Je n'utilise pas GCD car je dois prendre en charge iOS 3

+0

où 'runloopMethod' est-il défini? Je voudrais faire la même chose que vous faites, mais je suis un peu confus sur cette partie – abbood

Répondre

0

Je suppose que vous essayez d'utiliser des threads pour exécuter des tâches en arrière-plan afin de garder l'interface utilisateur sensible. C'est bien, mais ce serait une approche très difficile. Essayez ceci:

1) A partir du thread principal, déclencher un nouveau thread:

[NSThread detachNewThreadSelector:@selector(methodThatTheThreadWillRun) 
         toTarget:nil 
         withObject:nil]; 

2) Ecrire methodThatTheThreadShouldRun et faire tout ce que vous devez faire en elle. Il sera exécuté dans le thread que vous venez de créer. Quand il finit, faites appeler un threadIsFinished sur le thread principal:

- (void)methodThatTheThreadWillRun { 
    MyClass *myObject = [ [MyClass alloc] init ]; 
    [myObject method1]; 
    [myObject method2]; 
    [myobject release]; 
    [self performSelectorOnMainThread:@selector(threadIsFinished)]; 
} 

3) Enfin, écrire threadIsFinished:

- (void)threadIsFinished { 
    // do whatever you need to do here: stop a spinner, etc. 
    // this will be invoked by the background thread but will 
    // execute on the main thread 
} 
+0

@yep Alexantd, je tiens à répondre à l'interface utilisateur. Le problème lié à l'utilisation de detachNewThreadSelector ou de performSelectorInBackground est qu'il ne configure pas de boucle d'exécution. – subzero

1

La méthode Objectif C code d'exécution d'envoi n'a pas de mécanisme (AFAIK) pour déterminer implicitement s'il faut faire un appel de méthode générique sur un thread différent de celui en cours, vous devrez donc implémenter votre propre mécanisme d'appel en arrière-plan explicite, comme vous l'avez fait, en utilisant performSelector.

Si vous définissez waitUntilDone à YES lors de votre appel à votre thread d'arrière-plan à partir du thread principal, vous bloquerez toujours l'interface utilisateur.Si vous souhaitez que votre méthode1 s'exécute en arrière-plan et ne bloque pas l'interface utilisateur, définissez waitUntilDone sur NO et devez informer le thread principal de la fin de l'exécution (ou toute autre chose) à l'aide de execSelectorOnMainThread.

Vous pouvez également utiliser des files d'attente d'opérations pour envoyer des messages à la boucle d'exécution du thread d'arrière-plan.

+0

hotpaw2, merci pour votre réponse. Oui, j'ai réalisé à propos de l'indicateur YES/NO sur performSelector ...., c'était une erreur lors de la publication de mon code. Je ne suis pas familier avec les files d'attente des opérations, jusqu'à présent il semble que c'est une sorte de pool pour déclencher plusieurs méthodes/opérations en même temps, le point intéressant est: "Vous pourriez alternativement utiliser des files d'attente pour envoyer des messages à vous avez voulu dire, en utilisant performSelector: onThread ...? – subzero