2009-05-15 10 views
0

J'essaie d'appeler la fonction "Run" dans un nouveau thread. À l'heure actuelle, j'ai ce code en utilisant openMP qui n'exécute pas "Run" dans un nouveau thread. REMARQUE: je ne demande pas d'aide pour utiliser OpenMP. Ce code était juste une solution rapide. Je préférerais une méthode CreateThread() d'aller à ce sujet.Multithreading avec héritage (C++)

vector<ICommand*>* commands; 
string strInput; 
// For each command... 
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i) 
{ 
    // ...if the current command we're examining is valid... 
    if((*i)->ContainsCommand(strInput)) 
    { 
     // ...run it in a new thread and don't let ZChatInput handle it normally... 
     #pragma omp sections nowait 
     { 
     #pragma omp section 
      (*i)->Run(strInput); 
     #pragma omp section 
      bRet = false; 
     } 

     // ...and don't check any more commands. 
     break; 
    } 

} 

Alors, comment cela serait-il possible en utilisant simplement la norme et STL? Bien sûr, je cherche un moyen qui fonctionne :)

Répondre

0

Donc, je l'ai compris après avoir vérifié la documentation MSDN. Voici comment je l'ai fait, au cas où l'un de vous serait intéressé:

static vector<ICommand*>* commands; 
// This is what we pass to CommandOnThread. 
struct CommandParameter 
{ 
    string strInput; 
    ICommand* command; 
}; 

int CommandOnThread(CommandParameter* cp) 
{ 
    cp->command->Run(cp->strInput); 
    delete cp; 

    return 0; 
} 

void foo() 
{ 
    string strInput; 
    ... 
    // For each command... 
    for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i) 
    { 
     // ...if the current command we're examining is valid... 
     if((*i)->ContainsCommand(strInput)) 
     { 
      // Put the CP on the stack. 
      CommandParameter* temp = new CommandParameter; 
      if(temp == NULL) 
      { 
       Print("Out of memory!"); 
       bRet = false; 
       break; 
      } 

      // ...set up the parameters to createthread... 
      temp->strInput = strInput; 
      temp->command = *i; 

      // ...run it in a new thread... 
      CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CommandOnThread, temp, NULL, NULL); 

      // ...and don't check any more commands. 
      bRet = false; 
      break; 
     } 
    } 
} 
3

Comment utiliser Boost.Thread?

if((*i)->ContainsCommand(strInput)) 
{ 
    boost::thread t(boost::bind(&ICommand::Run, *i)); 
} 

Cela va exécuter "Exécuter" dans un thread détaché. (Notez que je n'ai pas testé cela.)

+0

Non, désolé. J'essaie de fuir les bibliothèques tierces. Si cette fonctionnalité est dans VS2010, alors je vais l'essayer; mais jusque-là, toujours pas ce que je cherche. De plus, vous avez oublié de transmettre strInput en tant que paramètre. –

+2

quel est le problème avec boost? C'est presque aussi standard que stl. Beaucoup de bibliothèques boost vont dans le nouveau standard et je ne serais pas impressionné si les threads boost devenaient le nouveau standard (je sais qu'il y a un nouveau standard pour les threads, mais je ne sais pas s'ils sont similaires au boost du thread modèle) –

+0

C++ 0x aura des fonctions de thread qui ressemblent à boost.thread. Voir http://en.wikipedia.org/wiki/C%2B%2B0x#Threading_facilities –

1

Voulez-vous vraiment créer un thread pour chaque commande? La création de threads est chère. Si vous avez absolument besoin que cette partie soit asynchrone - créez une file d'attente synchronisée, pré-spawn nombre de threads (c'est votre évolutivité ici), les bloquer sur la file d'attente, puis placez un message (pointeur?) Dans votre boucle .

Répondre à votre commentaire:

 
// setup 
sync_queue wq; // that would be protected by mutex and a conditional var or two 
for (i = 0; i < parallel_factor; ++i) start_thread(th_func, wq); 
... 

// your loop body : 
    ... 
    if (valid_input) q.put(item); 
    ... 

// thread function 
void th_func(sync_queue& q) 
{ 
    work_item* pwi; 
    while ((pwi = q.get())) do_it(pwi); 
} 

sens?

+0

Ce n'est pas créer un thread pour chaque commande. C'est seulement en créant le thread si l'entrée est valide, et pas plus. Cela DOIT être asynchrone, car il devient vraiment péniblement lent sinon. Je ne comprends pas votre stratégie de mise en œuvre. Pouvez-vous montrer un exemple de pseudocode? –

+0

Cela fonctionne ... mais il semble que beaucoup de travail pour une simple création de thread ... Il doit y avoir un meilleur moyen avec CreateThread ou un autre WinAPI. –

+0

Appelez-vous Run() pour chaque entrée valide? Ensuite, faites le (s) fil (aux) pré-démarré (s). Sinon, vous pourriez découvrir qu'il est plus lent, puis seul thread. Et, oui, jouer avec les threads demande beaucoup de travail. –

2
+0

Pouvez-vous me montrer dans le contexte du code que j'ai fourni? –

+0

similaire à l'exemple boost, vous utilisez un pointeur sur votre fonction en tant que paramètre et en haut il va. _beginthread et CreateThread sont les fonctions MS pour le multithread – DaClown

+0

int h = (HANDLE) _beginthreadex (NULL, 0, (* i) -> Exécuter, & strInput, 0, NULL); pas exactement sûr, et Run doit être une fonction _stdcall. C'est un win32 api – ryansstack

2

Vous pouvez essayer quelque chose comme ceci:

vector<ICommand*>* commands; 
string strInput; 

void CommandOnThread(void* command) 
{ 
    (ICommand*)command->Run(); 
} 

// For each command... 
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i) 
{ 
    // ...if the current command we're examining is valid... 
    if((*i)->ContainsCommand(strInput)) 
    { 
     //Attach the input to the command 
     (*i)->AttachInput(strInput); 
     _beginthread(CommandOnThread, 0, *i); 
     break; 
    } 
} 

Pour cela, vous devez changer l'interface de commande un peu pour passer l'entrée de commande en deux étapes: d'abord enregistrer l'entrée dans l'objet de commande, puis appelez Run() sans arguments. Vous pouvez remplacer _beginthread par CreateThread si vous aimez ils sont assez similaires. Pour clarifier: Vous ne pouvez pas utiliser une méthode d'instance comme paramètre de fonction pour _beginthread (ou CreateThread). La solution ci-dessus consiste à passer l'objet (commande) à la fonction puis à appeler sa méthode d'instance (Run). Cependant, dans ce cas, vous ne pouvez pas passer d'arguments supplémentaires à la fonction thread et, par conséquent, vous ne pouvez pas passer d'arguments à la méthode d'instance. La solution la plus simple consiste à attacher l'argument à l'instance avant de le passer à la fonction thread.

J'espère que cela aide. Bien sûr, cette solution n'est pas possible si vous ne pouvez pas modifier l'interface et l'implémentation de la classe Command.

+0

Où "AttachInput" est-il défini? De plus, vous ne passez aucun paramètre à command-> Run() –

+0

Vous devez le définir vous-même. Vous ne pouvez passer qu'un seul argument à la fonction thread et il est déjà utilisé pour passer l'objet commande. –