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

    join wartet, 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 du addmessage in einem eigenen Thread auf und nicht im Hauptthread?



  • @Quiche-Lorraine

    #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 tlogging beendet wird, bevor du addmessage aufrufst, start kommt aber nie zurück, daher wird addmessage auch 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.


Anmelden zum Antworten