2016-07-06 12 views
1

Ich muss einen Thread spawnen, wenn ein bestimmtes Triggerereignis innerhalb einer Klasse Foo empfangen wird. Das Triggerereignis wird von einer Winsock-Serverklasse empfangen, die einen Verweis auf die Variable triggerEvent enthält.Threading in objektorientierte, ereignisgesteuerte Anwendung

bool Foo::HandleEvents() 
{ 
    while (1) 
    { 
     // Other things are done at the top of this loop 

     switch (triggerEvent) 
     { 
      case 'h': 
      { 
       // I instantiate an object here to do 
       // what I need to do in the thread. 
       // I use a pointer that is a private 
       // member of Foo. 
       thingMaker = new ThingMaker(params); 

       // Spawn a new thread here calling a 
       // function of ThingMaker and using thingMaker 
       break; 
      } 
      case ...: return true; 
      default: break; 
     } 
    } 
} 

Da der Faden zu seinem Fall in den switch lokal ist, verliere ich Zugang zu ihm auf break. Ich kann join() nicht anrufen, weil ich mich mit der Echtzeitverarbeitung befasse und ich kann nicht auf den Thread warten, bis ich weiß, dass es fertig ist.

Ich fragte vor kurzem eine Frage über Threading here in Bezug auf die gleiche Anwendung und wurde gesagt, detach() ist eine schlechte Praxis; Ich denke auch, dass meine Frage zu vage war, da die angebotene Lösung nicht meinen Bedürfnissen entsprach und meine Anwendung sich seitdem in der Architektur geändert hat.

Ich habe auch versucht, den Thread in short-life-Manager-Klasse zu kapseln, die Instanzen von ThingMaker erstellt, aber ohne Erfolg.

Wie gehe ich vor? Ich vermute, mein Hauptproblem ist der Umfang, aber meine Möglichkeiten sind begrenzt. Foo::HandleEvents() kann nicht verzögert werden oder sonst verliere ich kritische Daten.

+3

Haben Sie ein System in Betracht gezogen, in dem Sie die Thread-Lebensdauern * kontrollieren *, z. B. einen Threadpool, in dem der gepostete Code Ihre 'params' in eine vom Pool überwachte Warteschlange sendet, damit die Arbeit ausgelöst wird? – WhozCraig

+0

Wie wäre es mit "Futures" zu tun? Hast du C++ 11? – Arunmu

+1

Warum nicht den 'thread' zu einem Mitglied der' Foo'-Klasse machen, dann hast du immer Zugriff darauf? Eine Frage, die ich habe, ist was willst du passieren, wenn der Thread noch ausgeführt wird, wenn 'HandleEvent' Funktion ausgelöst wird? Sie benötigen möglicherweise Daten Mitglied, um alle ausstehenden Threads zu verfolgen ... –

Antwort

1

Sie könnten einen std::map (oder einer der anderen ähnlichen Behältern):

class Foo 
{ 
    bool HandleEvents(); 
    std::map<ThingMaker*, std::thread> m_map; 
}; 

bool Foo::HandleEvents() 
{ 
    while (1) 
    { 
     switch (triggerEvent) 
     { 
      case 'h': 
      { 
       thingMaker = new ThingMaker(params); 
       m_map[thingMaker] = std::thread(function_ptr, thingMaker); 
      } break; 
      case 't': // termination event trigger 
      { 
       m_map[thingMaker].second.join(); 
       m_map.erase(thingMaker); 
       delete thingMaker; 
      } break; 
      case ...: return true; 
      default: break; 
     } 
    } 
} 

Da dieser offensichtlich nicht Ihren vollständigen Code, den Sie haben würde, den obigen Code anzupassen an Ihre Bedürfnisse anzupassen, aber Sie könnten den Schlüssel/Wert der Karte in der Vorlage austauschen oder stattdessen die Thread-ID verwenden, wenn dies sinnvoller wäre (z. B. std::map<std::thread::id, ThingMaker*>, usw.), aber etwas wie map vermeidet Iterationen über ein Array und join in jedem Thread Implementieren einer vollständigen Threadpoolimplementierung, wenn Sie nicht unbedingt eine benötigen.

Seitennotiz: Die Verwendung von detach ist nicht schlecht, in der Tat ist es ziemlich nützlich; Das Abtrennen eines Threads signalisiert dem Kernel, dass der Thread "bereinigt" werden kann, sobald er ausgeführt wurde (wodurch bestimmte Ressourcen und Handles freigegeben werden). Das Aufrufen von detach in einem Thread ist nützlich, wenn Sie wissen, dass Sie nicht mehr auf das zugrunde liegende Thread-Handle zugreifen müssen (wie in einem extrem kurzlebigen Thread). Es ist weder schlecht noch gut, einfach ein Werkzeug zu nutzen (wie die berüchtigte goto Aussage).

Hoffe, dass kann helfen.

+0

Super Antwort. Funktioniert super. Danke für die Erläuterung zu 'detach' auch. –