Kann jemand ein einfaches Beispiel für das Starten von zwei (objektorientierten) Threads in C++ posten.
Ich suche nach tatsächlichen C++-Thread-Objekten, auf die ich Run-Methoden (oder ähnliches) erweitern kann, anstatt eine Thread-Bibliothek im C-Stil aufzurufen.
Ich habe alle betriebssystemspezifischen Anfragen ausgelassen, in der Hoffnung, dass jeder, der geantwortet hat, mit plattformübergreifenden Bibliotheken antworten würde, die verwendet werden können. Ich drücke das jetzt nur explizit aus.
Diese Frage wird auf Meta diskutiert
– Zoe steht mit der Ukraine ♦
13. August 2019 um 12:46 Uhr
MasterMastix
Erstellen Sie eine Funktion, die der Thread ausführen soll, z.
Erstellen Sie nun die thread Objekt, das letztendlich die obige Funktion wie folgt aufruft:
std::thread t1(task1, "Hello");
(Du musst #include <thread> um auf die zuzugreifen std::thread Klasse)
Die Argumente des Konstruktors sind die Funktion, die der Thread ausführt, gefolgt von den Parametern der Funktion. Der Thread wird automatisch bei der Konstruktion gestartet.
Wenn Sie später warten möchten, bis der Thread mit der Ausführung der Funktion fertig ist, rufen Sie Folgendes auf:
t1.join();
(Beitreten bedeutet, dass der Thread, der den neuen Thread aufgerufen hat, darauf wartet, dass der neue Thread die Ausführung beendet, bevor er seine eigene Ausführung fortsetzt).
Der Code
#include <string>
#include <iostream>
#include <thread>
using namespace std;
// The function we want to execute on the new thread.
void task1(string msg)
{
cout << "task1 says: " << msg;
}
int main()
{
// Constructs the new thread and runs it. Does not block execution.
thread t1(task1, "Hello");
// Do other things...
// Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
t1.join();
}
Dies sollte für jedes Betriebssystem funktionieren, sofern Ihr Compiler diese Funktion (C++11) unterstützt.
@Preza8 VS10 unterstützt viele Funktionen in C++11 nicht. VS12- und VS13-Support-Thread.
– jodag
9. Januar 2014 um 0:53 Uhr
Im Kommentar “GCC-Versionen unter 4.7 verwenden -std=c++0x (anstatt -std=c++0x)” Ich glaube, das zweite “c++0x” sollte stattdessen “c++11” sein, aber das kann nicht geändert werden, weil die Bearbeitung zu klein ist.
– zentrunix
25. März 2014 um 16:19 Uhr
@MasterMastic Welchen Unterschied macht es, wenn wir anstelle von std::thread t1(task1, “Hallo”) std::thread t1(&task1, “Hallo”) verwenden und die Referenz der Funktion übergeben? Sollten wir die Funktion in diesem Fall als Zeiger deklarieren?
– Benutzer2452253
4. November 2014 um 16:32 Uhr
@ user2452253 Wenn Sie “task1” übergeben, übergeben Sie einen Zeiger auf die Funktion, die Sie ausführen möchten (was gut ist). Wenn Sie “&task1” übergeben, übergeben Sie einen Zeiger auf einen Zeiger einer Funktion, und die Ergebnisse wären wahrscheinlich nicht so hübsch und sehr undefiniert (es wäre, als würden Sie versuchen, zufällige Anweisungen nacheinander auszuführen. Mit der richtigen Wahrscheinlichkeit Sie nur vielleicht öffne das Tor zur Hölle). Sie möchten wirklich nur den Funktionszeiger übergeben (ein Zeiger mit dem Wert der Adresse, an der die Funktion beginnt). Wenn das die Dinge nicht klärt, lass es mich wissen und viel Glück!
– MasterMastic
4. November 2014 um 16:47 Uhr
@curiousguy Nun, der richtige Weg, dies zu tun, besteht darin, einen Zeiger auf die Funktion zu übergeben, die Sie ausführen möchten. In diesem Fall ist die Funktion task1. Daher wird der Funktionszeiger auch mit bezeichnet task1. Aber danke, dass Sie das angesprochen haben, denn ich glaube, ich habe mich geirrt und es ist gleichbedeutend mit &task1also spielt es keine Rolle, welche Form Sie schreiben (wenn ja, denke ich, dass Zeiger auf Zeiger der Funktion ist &&task1 — das wäre schlecht). Relevante Frage.
– MasterMastic
5. Juli 2018 um 9:22 Uhr
Eduard Kmett
Nun, technisch gesehen wird jedes solche Objekt über eine Thread-Bibliothek im C-Stil gebaut, weil C++ nur einen Bestand spezifiziert hat std::thread -Modell in c++0x, das gerade festgenagelt und noch nicht implementiert wurde. Das Problem ist etwas systemisch, technisch gesehen ist das vorhandene C++-Speichermodell nicht streng genug, um eine gut definierte Semantik für alle „passiert vorher“-Fälle zu ermöglichen. Hans Böhm hat vor einiger Zeit ein Papier zu diesem Thema geschrieben und war maßgeblich an der Ausarbeitung des c++0x-Standards zu diesem Thema beteiligt.
Allerdings gibt es mehrere plattformübergreifende Thread-C++-Bibliotheken, die in der Praxis gut funktionieren. Intel-Thread-Bausteine enthalten ein tbb::thread-Objekt, das dem c++0x-Standard sehr nahe kommt, und Boost hat eine boost::thread-Bibliothek, die dasselbe tut.
#include <boost/thread.hpp>
void task1() {
// do stuff
}
void task2() {
// do stuff
}
int main (int argc, char ** argv) {
using namespace boost;
thread thread_1 = thread(task1);
thread thread_2 = thread(task2);
// do other stuff
thread_2.join();
thread_1.join();
return 0;
}
Boost-Thread ist großartig – mein einziges Problem war, dass Sie (als ich es zuletzt benutzte) nicht auf das native zugrunde liegende Thread-Handle zugreifen konnten, da es sich um ein privates Klassenmitglied handelte! Es gibt eine MENGE Zeug in win32, für das Sie das Threadhandle brauchen, also haben wir es optimiert, um das Handle öffentlich zu machen.
– Orion Edwards
5. November 2008 um 19:40 Uhr
Ein weiteres Problem mit boost::thread besteht darin, dass Sie, soweit ich mich erinnere, nicht die Freiheit haben, die Stapelgröße des neuen Threads festzulegen – eine Funktion, die bedauerlicherweise auch nicht im c++0x-Standard enthalten ist.
– Eduard Kmett
5. November 2008 um 20:13 Uhr
Dieser Code gibt mir eine boost::noncopyable-Ausnahme für diese Zeile: thread thread_1 = thread(task1); Vielleicht liegt es daran, dass ich eine ältere Version (1.32) verwende.
– Frank
21. Februar 2009 um 0:42 Uhr
task1 wurde nicht in diesem Bereich deklariert?
– Jake Gaston
22. März 2019 um 20:45 Uhr
Caner
#include <thread>
#include <iostream>
#include <vector>
using namespace std;
void doSomething(int id) {
cout << id << "\n";
}
/**
* Spawns n threads
*/
void spawnThreads(int n)
{
std::vector<thread> threads(n);
// spawn n threads:
for (int i = 0; i < n; i++) {
threads[i] = thread(doSomething, i + 1);
}
for (auto& th : threads) {
th.join();
}
}
int main()
{
spawnThreads(10);
}
Hohenheimsenberg
Es gibt auch eine POSIX-Bibliothek für POSIX-Betriebssysteme. Überprüfen für Kompatibilität
Bei der Suche nach einem Beispiel einer C++-Klasse, die in einem neuen Thread eine ihrer eigenen Instanzmethoden aufruft, taucht diese Frage auf, aber wir konnten keine dieser Antworten so verwenden. Hier ist ein Beispiel, das das tut:
#include "DataManager.h"
void DataManager::getData()
{
// perform background data munging
hasData = true;
// be sure to notify on the main thread
}
bool DataManager::dataAvailable()
{
if (hasData)
{
return true;
}
else
{
std::thread t(&DataManager::getData, this);
t.detach(); // as opposed to .join, which runs on the current thread
}
}
Beachten Sie, dass dieses Beispiel nicht in Mutex oder Locking gerät.
Danke, dass du das gepostet hast. Beachten Sie, dass die allgemeine Form des Aufrufs einer Thread-on-Instance-Methode etwa so aussieht: Foo f; std::thread t(&Foo::Run, &f, args…); (wobei Foo eine Klasse ist, die ‘Run()’ als Mitgliedsfunktion hat).
– Jay Elston
8. Januar 2019 um 19:44 Uhr
Danke, dass du das gepostet hast. Ich verstehe ernsthaft nicht, warum alle Threading-Beispiele globale Funktionen verwenden.
– hk Battousai
15. Februar 2020 um 13:00 Uhr
Ändern Sie dies in shared_from_this, wenn die aktuelle Klasse von enable_shared_from_this abgeleitet ist.
– Eugen
1. Februar 2021 um 15:39 Uhr
Don Hatch
Sofern man keine separate Funktion in globalen Namespaces wünscht, können wir Lambda-Funktionen zum Erstellen von Threads verwenden.
Einer der Hauptvorteile beim Erstellen von Threads mit Lambda besteht darin, dass wir keine lokalen Parameter als Argumentliste übergeben müssen. Wir können die Erfassungsliste für dasselbe verwenden, und die Schließungseigenschaft von Lambda kümmert sich um den Lebenszyklus.
Hier ist ein Beispielcode
int main() {
int localVariable = 100;
thread th { [=](){
cout<<"The Value of local variable => "<<localVariable<<endl;
}};
th.join();
return 0;
}
Ich habe bei weitem festgestellt, dass C++-Lambdas die beste Methode zum Erstellen von Threads sind, insbesondere für einfachere Thread-Funktionen
Danke, dass du das gepostet hast. Beachten Sie, dass die allgemeine Form des Aufrufs einer Thread-on-Instance-Methode etwa so aussieht: Foo f; std::thread t(&Foo::Run, &f, args…); (wobei Foo eine Klasse ist, die ‘Run()’ als Mitgliedsfunktion hat).
– Jay Elston
8. Januar 2019 um 19:44 Uhr
Danke, dass du das gepostet hast. Ich verstehe ernsthaft nicht, warum alle Threading-Beispiele globale Funktionen verwenden.
– hk Battousai
15. Februar 2020 um 13:00 Uhr
Ändern Sie dies in shared_from_this, wenn die aktuelle Klasse von enable_shared_from_this abgeleitet ist.
– Eugen
1. Februar 2021 um 15:39 Uhr
Es hängt weitgehend von der Bibliothek ab, für die Sie sich entscheiden. Wenn Sie beispielsweise die wxWidgets-Bibliothek verwenden, würde die Erstellung eines Threads wie folgt aussehen:
Wenn Ihr Haupt-Thread die CreateThread-Methode aufruft, erstellen Sie einen neuen Thread, der mit der Ausführung des Codes in Ihrer „Entry“-Methode beginnt. Sie müssen in den meisten Fällen einen Verweis auf den Thread beibehalten, um ihm beizutreten oder ihn zu stoppen. Mehr Infos hier: wxThread-Dokumentation
Du hast vergessen den Thread zu löschen. Vielleicht wollten Sie eine erstellen losgelöst Gewinde?
– Aib
5. November 2008 um 18:57 Uhr
Ja, richtig, ich habe den Code aus einem Code extrahiert, an dem ich gerade arbeite, und natürlich wird der Verweis auf den Thread irgendwo gespeichert, um ihn später zu verbinden, zu stoppen und zu löschen. Danke. 🙂
– LorenzCK
6. November 2008 um 16:06 Uhr
9894500cookie-checkEinfaches Beispiel für Threading in C++yes
Diese Frage wird auf Meta diskutiert
– Zoe steht mit der Ukraine
♦
13. August 2019 um 12:46 Uhr