Thread über TTimer abschiessen
-
jap
-
Hallo Manfred Schmidtke,
kann es sein, dass dein Thread nicht 2 Sekunden benötigt und der Timer bereits disabled ist?Evi48
-
In diesem Falle kaum. Execute kann sich wegen einer Endlosschleife garnicht beenden und läuft auch fröhlich nach Stunden weiter. Die Endlos-Schleife ist auch nur zum Test eingebaut, weil dies einfacher ist, als einen toten Prozess unter Windoof zu erzeugen.
Nachtrag: Liegt es vielleicht an der NULL für den Owner, was kann ich ohne Formular da sonst angeben?
-
nein, an dem NULL liegt es nicht.
Du überprüfst in Deiner Threadroutine die Eigenschaft Terminated?
-
Ich denke da ist der Kern des Übels Joe_M. hat glaube ich Recht denn in der Hilfe steht:
Terminate setzt die Eigenschaft Terminated des Thread auf true und signalisiert, daß der Thread so bald wie möglich beendet werden sollte. Im Gegensatz zu der Windows-API-Methode TerminateThread, die den Thread sofort beendet, fordert die Methode Terminate den Abbruch des Thread nur an. Dadurch kann der Thread vor seiner Beendigung noch erforderliche Aufräumarbeiten durchführen.
Die Methode Execute eines Threads sowie alle von Execute aufgerufenen Methoden sollten die Eigenschaft Terminated regelmäßig abfragen und die Ausführung gegebenenfalls beenden.
Evi48
-
Auf Terminated in Execute zu prüfen ist sicherlich sinnvoll und jetzt auch eingebaut.

Löst aber des eigentliche Problem nicht, da Terminated niemals gesetzt wird. Die Timer-Funktion erhält keinen Aufruf.
-
Was steht denn in der Hilfe zu TThread::WaitFor()?
-
Es liegt offenbar nicht am Timer. Ich hab den ganzel Thread-Krempel in das Hauptformular übertragen und dort ganz normal eine Komponente angelegt.
Auch hier das gleiche Bild. Nach Aufruf von WaitFor geht nur noch Execute.
Die Idee war, den Thread von aussen abzuschießen. Dieser müsste doch unabhängig vom Hauptprogramm vor sich hin laufen. Warum kommt im Hauptprogramm kein Event an?
-
ja eben, WaitFor wartet auf das Ende des Threads...
-
Dann ist die Thread-Kiste (zumindest über VCL) wohl ein Holzweg

Welche Möglichkeiten bleiben da noch?

-
Möglichkeiten für was denn überhaupt?
-
Es geht darum, dass der auskommentierte Funktionsaufaufruf
CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe32.th32ProcessID);abstürzen kann, wenn th32ProcessID auf einen abgestürzten Prozess abfragt. Dieser Zustand ist sicherlich selten aber aufgrund der Anzahl der Anwender nicht tragbar.
Die bei diesem Aufruf ermittelten Informationen (es geht um den Ausführungspfad des Prozesses) sind zwar sinnvoll, aber im Einzelfall (eben Absturz des Prozesses) nicht so wichtig.
Ich muss daher in der Lage sein, den Funktionsaufruf irgendwie zu canceln. Ähnlich der Windows-Funktion "... Anwendung reagiert nicht mehr".
-
Nachdem mir jetzt auch klar ist, dass die Hauptanwendung bei WaitFor nix mehr tut außer zu warten, den Timer in den Thread selbst verlagert.
Jetzt aber die Überraschung: Auch hier gibt es kein Timer-Event!!
Ist Application->ProcessMessages hier falsch?
-
Schau Dir mal die WinAPI Funktion WaitForSingleObject an, ich denke das ist das, was Du suchst.
-
Vielen Dank an Joe_M und alle Anderen

So läufts:
HANDLE hModuleSnap = INVALID_HANDLE_VALUE; m_thgetModule = new thgetModule (false, pe32.th32ProcessID); if (m_thgetModule) { //Auf Ende Warten WaitForSingleObject ((HANDLE) m_thgetModule->Handle, 2000); //Thread anhalten m_thgetModule->Suspend(); //Ergebnis holen hModuleSnap = m_thgetModule->m_hModuleSnap; //Thread beenden m_thgetModule->Terminate(); delete m_thgetModule; }Kein Timer mehr!
Der Aufruf des Constructors mit false macht aber lustige Sachen. Der Thread startet, noch während der Constructor arbeitet!??!
Suspend ist notwendig, da es sonst ein Timinig-Problem mit Terminate() gibt und es knallt beim Delete.
-
Manfred Schmidtke schrieb:
Suspend ist notwendig, da es sonst ein Timinig-Problem mit Terminate() gibt und es knallt beim Delete.
???
Hast Du überhaupt schon mal in die Hilfe zu TThread geschaut?
-
Selbstverfreilich. Aber
Terminate ruft die Funktion PostQuitMessage der Windows-API auf, um die Anwendung kontrolliert zu beenden. Die Methode Terminate wirkt somit nicht direkt.
Mag ja sein, dass ich ein bisschen begriffsstutzig bin, aber der Hilfe kann ich immernoch nicht entnehmen, dass ein Aufruf von Suspend vor Terminate und delete notwendig ist. Wie dem auch sein, darauf bin ich ja schließlich auch selbst gekommen.
Klar ist mir jedoch weiterhin nicht, warum das Timer-Event auch innerhalb des Threads nicht gefunzt hat.
Aber was solls, funzt mit WaitForSingleObject prima und wesentlich einfacher. Nochmals Danke.
-
Dieses Zitat ist aus der Hilfe zu TApplication::Terminate(), in der Hilfe zu TThread steht etwas anderes.
-
Sorry, falsch kopiert (aber richtig gelesen!).
Terminate setzt die Eigenschaft Terminated des Thread auf true und signalisiert, daß der Thread so bald wie möglich beendet werden sollte. Im Gegensatz zu der Windows-API-Methode TerminateThread, die den Thread sofort beendet, fordert die Methode Terminate den Abbruch des Thread nur an. Dadurch kann der Thread vor seiner Beendigung noch erforderliche Aufräumarbeiten durchführen.
Wenn jetzt in der Execute-Funktion auf Terminate geprüft und die Funktion beendet wird, warum schlägt das delete dann trotzdem fehl?
Terminate() setzt lediglich FTerminated und damit die Eigenschaft Terminated auf true. Die Funktion Execute fragt in der Schleife zunächst auf Terminated ab, und beendet sich. Dies geschieht jedoch zeitlich nach dem delete. Verwundert war ich auch darüber, das Execute schon aufgerufen wird, bevor überhaupt der Constructor abgearbeitet ist, wenn mit CreateSuspended = false aufgerufen wird, was ja in diesem Falle notwendig ist. Warum ist schon klar, da schon der Constructor von TThread selbiges macht.
Aber, worüber diskutieren wir hier eigentlich? :p
-
Das delete schlägt einzig und allein deswegen fehl, weil der Thread mit FreeOnTerminate = true erzeugt wird. Durch das 'Suspenden' verhinderst Du nur, dass der Thread weiter ausgeführt wird und sich selbst freigibt.