2009-09-19 9 views
0

class MyClass { public: void DoSomething() {}; };Filetage d'une fonction membre à l'intérieur d'un vecteur de classes

std::vector<MyClass> A; 

int main(int argc, char* const argv[]) 
{ 
    MyClass a; 
    A.push_back(a); 
    boost::thread newThread(&MyClass::DoSomething, &A.back()); 
} 

Il compile, mais, normalement, il ne fonctionne pas. De l'aide?

+0

Non, il ne compile pas. –

+0

Oups, désolé. Devrait compiler maintenant. –

Répondre

0

(Par manque d'autre entrée, je suppose que vous travaillez sur une version VS, sur une version de Windows).

(1) Je suppose que vous essayez de passer & A.back comme un argument 'this' implicite. Cela ne fonctionnerait pas pour les fonctions membres régulières, qui sont définies comme __thiscall - ce qui signifie que la fonction attend l'argument 'this' dans le registre ecx et pas sur la pile. Essayez de déclarer DoSomething comme stdcall ou static (avec un argument explicite 'this').

(2) Supprimer l'adresse de fonction. Boost :: constructeur de fil nécessite le premier argument d'être 'callable' tout comme:

boost::thread newThread(MyClass::DoSomething, &A.back()); 

pourrait éventuellement travailler.

4

Le premier problème est que votre fonction principale génère un thread, puis quitte immédiatement. Le thread aura à peine une chance de s'exécuter avant la fin du processus. Donc, au minimum, vous devez attendre le fil pour terminer, que vous pouvez le faire en ajoutant newThread.join() à la fin de main, ainsi:

int main(int argc, char* const argv[]) 
{ 
    MyClass a; 
    A.push_back(a); 
    boost::thread newThread(&MyClass::DoSomething, &A.back()); 
    newThread.join(); 
    return 0; 
} 

L'autre question que vous est ai l'objet thread dans le même portée comme main, en tant que variable locale. Alors que vous pouvez le faire dans des situations simples, vous devez faire attention à la portée de l'objet boost::thread, qui doit lui donner une durée de vie au moins aussi longue que vous attendez que votre thread s'exécute. Dans le cas où un objet doit exécuter un thread sur une fonction membre, il vaut probablement mieux encapsuler l'objet thread dans l'objet, et avoir une méthode run() simple qui démarre le thread de travail. De cette façon, vous pouvez encapsuler toute la gestion des états et des threads au même endroit, ainsi que les mutex et les variables de condition dont vous pourriez avoir besoin. Un exemple simple serait quelque chose comme:

class Worker 
{ 
public: 

    Worker(); 

    void start(int N) 
    { 
     m_Thread = boost::thread(&Worker::processQueue, this, N); 
    } 

    void join() 
    { 
     m_Thread.join(); 
    } 

    // Worker thread where all processing occurs 
    void processQueue(int N); 

private: 

    boost::thread m_Thread; 
}; 

Vous voudrez probablement aussi ajouter des choses comme un drapeau qui retourne l'état de fil (par exemple la course, terminée, en attente, etc.). J'ai remarqué que votre exemple utilise un vecteur d'instances d'objets (par exemple, le stockage par valeur). Veillez juste à ne pas finir par exécuter des opérations qui provoquent la création implicite d'une copie, car cela peut causer toutes sortes de problèmes avec les threads. (C'est pourquoi l'objet boost::thread est non-copiable.)

J'ai écrit un article sur threading with Boost qui explique les différentes façons de créer des threads, y compris comment exécuter des threads sur les fonctions membres (voir type 5).

+0

C'est un bon article que vous avez là. J'aurais aimé qu'il y ait quelque chose comme ça dans la documentation actuelle sur le boost, j'ai passé beaucoup de temps à regarder et avant que je comprenne tout, mais le tien a tout :-) – teeks99

+0

Merci!J'ai essayé d'écrire ce que j'ai trouvé manquant quand je l'ai appris. J'ai deux autres articles sous forme de brouillon, que j'espère publier bientôt. – gavinb

Questions connexes