Klassenfunktion mit Parameter als Thread
-
@Helmut-Jakoby sagte in Klassenfunktion mit Parameter als Thread:
// Wir brauchen ein Objekt der Klasse
Das ist nicht korrekt.
Er kann einfach eine Lambda-Funktion verwenden, und in ihr die Funktion auf dem Objekt (std::thread / Cfunktion) aufrufen.
Ein ähnliches Thema gab es hier erst kürzlich. Dynamische Parameterbindung und so.
-
Das wäre dann in etwa wie folgt: https://www.c-plusplus.net/forum/post/2624561
-
Vielen Dank.
Die Antworten haben mir sehr geholfen.
-
Gerne möchte ich die Funktion als Thread ausführen und ihm neue Nachrichten zukommen lassen. Dafür habe ich 2 Funktionen. Leider wird zwar der Logger (zum Speichern angedacht) ausgeführt. Doch es werden keine neuen Nachrichten ausgegeben (/gespeichert).
Kann es an dem lock eventuell liegen?
void clogging::start() { std::cout << "logging start" << std::endl; while (1!=0) { if (mutex.try_lock()) { if(vsmessage.size()==0) { } else if(vsmessage.size()>0) { std::cout << vsmessage << std::endl; vsmessage.pop_back(); } else { } mutex.unlock(); } else { mutex.unlock(); } // for cpu and add new message mutex.unlock(); std::this_thread::sleep_for(500ms); } } void clogging::addmessage(std::string stext) { std::cout << "addmessage" << std::endl; while (true) { if (mutex.try_lock()) { std::cout << "job shared (" << " message " << ")\n"; vsmessage.push_back(stext); mutex.unlock(); return; } else { vsmessage.push_back(stext); std::cout << "job exclusive (" << " message " << ")\n"; } mutex.unlock(); std::this_thread::sleep_for(500ms); } }clogging logging; std::thread tlogging(&clogging::startA, &logging); tlogging.join(); std::string msg = "Hallo Welt"; std::thread t1(&clogging::addmessageA, &logging, msg); t1.join();Vielen Dank im Voraus!
-
@no_name1991 Kannst du den Code so zusammen stellen, dass wir direkt ein kompilierbares Beispiel haben? Dann müssen wir nicht annehmen, wo der Mutex lebt, in welchem Kontext deine Threads erstellt werden und sehen schneller, wo die Probleme liegen können.
-
ich entschuldige mich dafür und reiche hier meinen Code (compilierbar) nach:
#include <algorithm> #include <filesystem> #include <fstream> #include <iostream> #include <string> #include <mutex> #include <thread> using namespace std::chrono_literals; class clogging{ private: std::vector<std::string> vsmessage; std::mutex mutex; protected: public: void start() { std::cout << "logging start" << std::endl; while (1!=0) { if (mutex.try_lock()) { if(vsmessage.size()==0) { } else if(vsmessage.size()>0) { std::cout << vsmessage[0] << std::endl; vsmessage.pop_back(); } else { } mutex.unlock(); } else { } std::this_thread::sleep_for(500ms); } } void addmessage(std::string stext) { std::cout << "addmessage" << std::endl; while (true) { if (mutex.try_lock()) { vsmessage.push_back(stext); mutex.unlock(); return; } else { } std::this_thread::sleep_for(500ms); } }; }; int main() { clogging logging; std::thread tlogging(&clogging::start, &logging); tlogging.join(); std::string msg = "Hallo Welt"; std::thread t1(&clogging::addmessage, &logging, msg); t1.join(); return 0; }
-
@no_name1991
Da fehlt noch der Vektor include
https://en.cppreference.com/w/cpp/thread/thread/join.html
joinwartet, dass der Thread beendet wird. Da du da eine unendlich Schleife drinnen hast, wird das aber nie passieren.Edit:
int main() { clogging logging; std::thread tlogging(&clogging::start, &logging); std::string msg = "Hallo Welt"; std::thread t1(&clogging::addmessage, &logging, msg); tlogging.join(); t1.join(); return 0; }so siehst du zumindest eine Ausgabe

-
@no_name1991
Mal eine Frage: Warum rufst duaddmessagein einem eigenen Thread auf und nicht im Hauptthread?
-
#include <algorithm> #include <filesystem> #include <fstream> #include <iostream> #include <string> #include <mutex> #include <thread> using namespace std::chrono_literals; class clogging{ private: std::vector<std::string> vsmessage; std::mutex mutex; protected: public: void start() { std::cout << "logging start" << std::endl; while (1!=0) { if (mutex.try_lock()) { if(vsmessage.size()==0) { } else if(vsmessage.size()>0) { std::cout << vsmessage[0] << std::endl; vsmessage.pop_back(); } else { } mutex.unlock(); } else { } std::this_thread::sleep_for(500ms); } } void addmessage(std::string stext) { std::cout << "addmessage" << std::endl; while (true) { if (mutex.try_lock()) { vsmessage.push_back(stext); mutex.unlock(); return; } else { } std::this_thread::sleep_for(500ms); } }; }; int main() { clogging logging; std::thread tlogging(&clogging::start, &logging); tlogging.join(); std::string msg = "Hallo Welt"; //std::thread t1(&clogging::addmessage, &logging, msg); //t1.join(); logging.ddmessage(msg); return 0; }Dieser Code gibt nur die als Output "logging start" aus.
Mein Ziel ist es, Ein/-Ausgaben, Zustände etc auszugehen bzw diese eventuell auf Festplatte zu speichern.
Dies soll dann das restliche Programm nicht blockieren (warten bis die HDD etc es beendet hat).
-
@no_name1991 Du wartest darauf das
tloggingbeendet wird, bevor duaddmessageaufrufst,startkommt aber nie zurück, daher wirdaddmessageauch schon nicht aufgerufen.
-
@Schlangenmensch
Vielen Dank für die Erklärung.Wie muss man den Code verändern, wenn man vsmessage etwas hinzufügen möchte und der Thread parallel abgearbeitet werden soll?
Vielen Dank im Voraus.
-
Hallo @no_name1991 ,
in einem Projekt habe ich mich mal mit einem Threads beschäftigt, der über eine Message-Queue Nachrichten bekam, die dieser abgearbeitet hat. War die Queue abgearbeitet, würde der Threads "schlafen gelegt". Würde etwas in die Queue abgelegt, würde der Threads "aufgeweckt". Das Einfügen und Entnehmen aus der Queue würde mit einem Mutex abgesichert. Wärend der Threadarbeit könnten andere Threads etwas in die Queue einfügen. Das ganze ist mMn nur sinnvoll, wenn der Threads auch gut zu tun hat.
Du solltest prüfen, ob eine einfache Ausgabe im Ablauf ohne zusätzlichen Thread nicht sinnvoller wäre.