Guten Morgen,
ich möchte einen Thread in eine eigene Klasse unterbringen. Danach soll
diese von einer anderen Klasse zugriff besitzen.
WIe kann ich in C++ einen Thread in eine eigene Klasse unterbringen?
Hat jemand das schon einmal gemacht?
Ich hab mal jetzt eine Klasse Thread erstellt.
Nun erscheint immer folgende Fehlermeldung:
>>'CreateThread' : Konvertierung des Parameters 3 von 'unsigned long' in >>'unsigned long (__stdcall *)(void *)' nicht moeglich>>Keine Funktion mit diesem Namen im Gueltigkeitsbereich stimmt mit dem >>Zieltyp
ueberein
Die Threadfunktion my_thread muss statisch sein, wie bei jeder anderen
Anwendung auch, bei der Callback-Funktionen verwendet werden. Was erst
recht nicht geht ist eine virtuelle Funktion.
Den this-Pointer Deines Objektes muss Du von Hand mitliefern und in der
my_thread-Funktion explizit auswerten.
Allerdings spricht nichts dagegen, dann unmittelbar eine andere Funktion
des Objektes aus dieser statischen Threadfunktion heraus aufzurufen, und
die mag dann auch gerne virtuell sein.
Also:
Ob Deine "status"-Auswertung so irgendeinen Sinn hat, will ich jetzt
nicht weiter untersuchen. Du könntest einfach in der statischen
Threadfunktion ein Flag setzen, bevor die nichtstatische Threadfunktion
aufgerufen wird und dieses wieder löschen, wenn diese zurückkehrt, aber
das wertet naturgemäß den suspend-Zustand nicht aus. Braucht man das?
Hallo Rufus,
danke für die Unterstützung. Leider klappt habe ich jetzt ein anderes
Problem. Der Thread wird überhaupt nicht gestartet. Ich habe das ganze
jetzt mal soweit reduziert, dass ich nur die Thread Klasse benutze. Das
heisst ohne irgendwelche Ableitung usw. Was mache ich da falsch. Der
Thread läuft überhaupt nicht.
Nur als Bemerkung:
CreateThread solltest du besser nicht benutzen, wenn du C++
programmierst. Denn CreateThread ist eine WinAPI-Funktion, die
C++-runtime-library bekommt davon nichts mit. Das muss sie aber, um
bestimmte thread-lokale Variablen zu initalisieren. Aus dem Grund gibt
es _beginthread und _beginthreadex.
Aus ähnlichen, aber schwerwiegenderen Gründen ist TerminateThread in C++
absolut tabu (abgesehen von ganz seltenen Ausnahmefällen). Stichpunkt
Destruktoren und belegte Resourcen, das kann ganz schnell zu Deadlocks
führen. Sowas löst man üblicherweise über Events.
Zu deiner Thread-Funktion: Den Parameter "unused" zu nennen ist ein
wenig irreführend, da er offensichtlich nicht "unused" ist. Das ist
übrigens auch dein Fehler: Du machst irgendwas mit dem Parameter der
Thread-Funktion, gibst aber _beginthread eine 0 für diesen Parameter
(wieso _beginthread und nicht CreateThread s.o.).
Außerdem übergibst du _beginthread einen Zeiger auf my_Thread. Das ist
aber nicht erlaubt ohne ein führendes & um die Adresse der Funktion zu
bekommen (das ist einer der Unterschiede zwischen C und C++). Das du
dafür keinen Fehler oder Warnung bekommst, spricht möglicherweise für
einen veralteten Compiler.
Ok eins habe ich noch vergessen zu erwähnen. Diese Klasse Thread habe
ich auf meinem Heim-PC mit Microsoft Visual Studio C++ versucht zum
laufen zu bringen. Tut sich nichts!
In der Firma habe ich einen Embedded-PC (32 Bit) und da drauf läuft ein
Echtzeitbetriebssystem. Dieses Programmiere ich mit Microsoft Visual 6.0
C++.
Auf diesem System gibt es noch andere Thread die laufen. Diese wurden
auch mit createThread erzeugt und funktioniert. Allerdings habe ich
diese Threads nicht programmiert. Fakt ist ich habe meinen Thread schon
mal auf meinem Embedded-PC am laufen gehapt. Ich weiss nicht mehr
weiter.Nur für testzwecke habe ich mir die Klasse Thread kopiert und auf
meinem heim-PC ausprobiert.
Also CreateThread müsste gehen! Aber weiss leider nicht mehr weiter!
> Also CreateThread müsste gehen!
Ja, CreateThread "geht" schon; es wird ein neuer Thread erzeugt, der
auch einwandfrei laufen kann. Probleme werden aber auftreten, sobald du
bestimmte Funktionen der C-Runtime-Lib aufrufst. Im Prinzip sind für
einen mit CreateThread erzeugten Thread alle Standard-Funktionen
verboten, die intern über einen globalen Status verfügen.
Andernfalls würden verschiedene Threads dieselben, unsynchronisierten
Status-Variablen benutzen, was zwangsläufig zu Problemen führen wird;
nicht unbedingt Crashs, aber sehr schwer zu findende Bugs, sogenannte
Heisenbugs.
Hast du mal mit einem Debugger geschaut, ob der Thread tatsächlich nicht
anläuft?
Wie gesagt: Dein Fehler im letzten Code ist, dass die Thread-Funktion
einen Parameter bekommt, der ganz und gar nicht "unused" ist. Deswegen
musst du diesen Parameter natürlich auch beim _beginthread-Aufruf
bereitstellen. Du möchtest dort anscheinend den this-Zeiger übergeben.
Die Anzahl der C-Runtime-Routinen mit internem Statuscode ist
glücklicherweise überschaubar, in den etwa 14 Jahren, in denen ich mit
Threads unter Win32 arbeite (ja, seit einer Beta-Version von NT3.1) hat
der Gebrauch von CreateThread mir noch keine Probleme bereitet.
Allerdings gebrauche ich C-Runtime-Routinen eher konservativ, sowas wie
strtok fasse ich nicht an.
"Erfreulicherweise" schreibt auch die MS-Dokumentation zu
CreateThread/_beginthread im wesentlichen nur das, was Chris angeführt
hat, jedoch wird nicht erwähnt, welche Runtime-Routinen überhaupt
interne Statuscodes verwenden.
Ganz wichtig aber ist, daß man mit der richtigen Ausgabe der
C-Runtime-Library linkt, da ist statt "singlethreaded" "multithreaded"
zu wählen.
@X_Rider:
Ich habe die Variablennamen in meinem Beispiel sehr bewusst gewählt;
Deine "unused"-Spielerei verschleiert das Problem, wie Chris schon
nahelegte.
Zum Beenden eines Threads bietet sich die Verwendung eines
Synchronisationsobjektes wie z.B. ein Event an.
Das wird mit CreateEvent erzeugt, mit SetEvent gesetzt und kann mit
WaitForSingleObject ausgewertet werden.
Die Schleife in der Threadfunktion sollte zyklisch WaitForSingleObject
aufrufen und den Rückgabewert auswerten, damit kann dem Thread sauber
der Beendigungswunsch mitgeteilt werden.
Eine Endlosschleife ohne Zeitrückgabe macht den Windows-Scheduler
unglücklich.
Welches Echtzeit-OS verwendest Du/Deine Firma denn da, etwa OnTime
RTOS-32?
Wie kann ich überprüfen ob der Thread läuft? Ich habe mal einem
Breakpoint in der ThreadFunktion gesetzt. Da hält mein Programm nicht
an. Funktioniert nicht der Thread.