![]() |
Problem mit Thread in der Klasse
Ich habe leider bei der Verwendung eines Threads in meiner Klasse ein Absturtzproblem, der Compiler meldet weder Warnings noch Fehler. Hier ein Codestück:
Delphi-Quellcode:
Die erste MessageBox erscheint, dann crasht das Programm. Ich gehe davon aus, dass es ein Problem ist, vom Thread aus auf class member zuzugreifen, was ich jedoch nicht ganz verstehe, da der Thread selbst eine Methode dieser Klasse ist. Ich arbeite mit Delphi7. Wenn mir hier jemand weiter helfen könnte, wäre ich euch sehr verbunden, Danke! (-;
type
TXxxxxxx = class private //... bActive_ : Boolean; public //... constructor Create; procedure WorkThread(); property bActive : Boolean read bActive_ write bActive_ ; end; implementation constructor TXxxxxxx.Create; var ThreadID : Cardinal; begin //... CreateThread(nil, 0, @TXxxxxxx.WorkThread, nil, 0, ThreadID); end; procedure TXxxxxxx.WorkThread; begin while true do begin MessageBox(0,'1','',MB_OK); if bActive_ then begin end; MessageBox(0,'2','',MB_OK); end; end; end. MfG Mega |
DP-Maintenance
Dieses Thema wurde von "Matze" von "Programmieren allgemein" nach "Sonstige Fragen zu Delphi" verschoben.
Delphi-Frage |
Re: Problem mit Thread in der Klasse
MessageBox und Co sind nicht threadsicher. Du kannst sie also nicht direkt in einem Thread verwenden. Das gilt auch für alle VCL-Komponenten.
Leite deine Klasse von TThread ab und verwende die 'Synchronize'-Methode. |
Re: Problem mit Thread in der Klasse
Ich versichere, es liegt nicht an den Messageboxen.
Delphi-Quellcode:
--> Crash nachdem auf den OK-Button der 1. Messagebox gedrückt wurde
procedure TXxxxxxx.WorkThread;
begin while true do begin MessageBox(0,'1','',MB_OK); if bActive_ then begin end; MessageBox(0,'2','',MB_OK); end; end;
Delphi-Quellcode:
--> Nach bestätigen kommt immer wieder die selbe Messagebox, kein Crash
procedure TXxxxxxx.WorkThread;
begin while true do begin MessageBox(0,'1','',MB_OK); end; end;
Delphi-Quellcode:
--> sofortiger Crash
procedure TXxxxxxx.WorkThread;
begin while true do begin if bActive_ then begin end; end; end; Hat noch jemand eine Idee? Thx, Mega. |
Re: Problem mit Thread in der Klasse
Bitte, wenn du meinst. :roll: ("Nicht threadsicher" <> "Führt garantiert zum Absturz")
Befolge meinen Rat: 1. Lies nochmal, wie man 'CreateThread' genau aufruft. Dort wird ein Zeiger auf eine Prozedur erwartet, Du übergibst einen Methodenzeiger. Vielleicht liegt es daran. 2. Verwende eine Ableitung der Klasse 'TThread' und erspare Dir Lowlevelfrust. |
Re: Problem mit Thread in der Klasse
> Bitte, wenn du meinst. :roll: ("Nicht threadsicher" <> "Führt garantiert zum Absturz")
- MessageBox alleine crasht nicht - Klassenzugriff alleine crasht Also liegt es zumindest in diesem Fall am Klassenzugriff. Die Messageboxes habe ich auch nur als Debuggingmittel verwendet, sie sollen im fertigen Programm nicht mehr im Thread laufen. > 1. Lies nochmal, wie man 'CreateThread' genau aufruft. Dort wird ein Zeiger auf eine Prozedur erwartet, Du übergibst einen Methodenzeiger. Vielleicht liegt es daran. Ich glaube hier ist der Knackpunkt, bei C++ muss man invoken damit es funktioniert, aber ich habe nicht gefunden, wie man das bei Delphi umsetzt. > 2. Verwende eine Ableitung der Klasse 'TThread' und erspare Dir Lowlevelfrust. Habe ich ursprünglich verwendet, aber wie soll ich in der TWorkThread.Execute auf Klassenelemente von TXxxxxxx zugreifen (vermutet nichts Falsches hinter der Klasse, ich habe sie nur unkenntlich gemacht). Meine vorrübergehende Lösung: Ich packe den Programmteil, der in einem Thread laufen soll, in eine ganz normale Methode. Diese Methode rufe ich dann im Hauptprogramm nach dem Create des Objekts nach Bauplan der Klasse in einem Thread auf. Das funktioniert soweit, entspricht aber nicht ganz der Modularität/OOP. Wenn jemand noch eine Idee hat, wie man in Delphi invoked oder das Problem andersweitig löst, vielen Dank! (: MfG Mega. |
Re: Problem mit Thread in der Klasse
Messageboxen sind threadsafe. ShowMessage icst nicht threadsafe, da es zur VCL gehört.
Wenn du trotzdem die API Funktion in einer Klasse verwenden willst, dann musst du aus der Threadfunktion eine Methode machen. Eine Methode einer Klasse hat immer noch einen unsichtbaren Self-Parameter, somit stimmt die Signtur nicht mit der Signatur der Threadfunktion überein. Eine Lösung habe ich hier: ![]() Desweiteren solltest du nicht CreateThtrrad, sondern BeginThread nutzen. Da BeginThread die globale Variable IsMultithreaded auf true setzt und so den Heap threadsafe macht. |
Re: Problem mit Thread in der Klasse
Ah, Luckie. Hups. :oops:
Siehst du, man sieht den Wald vor lauter Bäumen nicht. Du hast eine Klasse deklariert und übergibst einen Methodenzeiger. Obwohl, nee. Das ist gar kein Methodenzeiger, denn da ist ja kein Objekt instantiiert. Innerhalb der Methode greifst Du aber auf eine private Variable der Klasse zu. Ohne Objekt geht das immer in die Hose. Also nochmal:
Delphi-Quellcode:
Type
TMyThread = Class (TThread) fmyObject : TWhatever; protected Procedure Execute; Override; Public Constructor Create (aMyObject : TWhatever); End; Constructor TMyThread.Create (aMyObject : TWhatever); Begin Inherited Create(True); // noch nicht loslaufen; fMyObject := aMyObject; Resume; // Und ab End; Procuedre TMyThread.Execute; Var anotherObject : TMyObject; Begin anotherObject := TMyObject.Create; Try While Not Terminated Do Begin DoSomething (fMyObject); DoSomethingElse (anotherObject); End Finally anotherObject.Free; End; End; ... Begin MyObject := TMyObject.Create; MyThread := TMyThread.Create (MyObject); ... MyThread.Terminate; MyThread.WaitFor; FreeAndNil (MyThread); Zitat:
|
Re: Problem mit Thread in der Klasse
Hallo,
@Luckie: Danke, genau das habe ich gesucht! So funktioniert es jetzt auch. (-: @alzaimar: >Innerhalb der Methode greifst Du aber auf eine private Variable der Klasse zu. Ohne Objekt geht das immer in die Hose. Ein klares "falsch"! Der Bauplan für ein Objekt ist eine Klasse. Methoden sind Proceduren/Funktionen, die Member der Klasse sind. Methoden können auf interne(private) und externe(public) Variablen (jedoch nicht properties) zugreifen! Das ganze auch ohne Objekt! Logischerweise wird der Code einer Methode einer Klasse erst dann ausgeführt, wenn ein Objekt nach dem Bauplan der Klasse erschaffen wurde und die Methode aufgerufen wird.
Delphi-Quellcode:
Das hier funktioniert, wenn die Methode nun nicht gerade als Thread aufgerufen wird, obwohl die Methode WorkThread (nicht vom Namen irritieren lassen) die private Variable bActive_ benutzt. (-;
type
TXxxxxxx = class private //... bActive_ : Boolean; public //... procedure WorkThread(); property bActive : Boolean read bActive_ write bActive_ ; end; implementation procedure TXxxxxxx.WorkThread; begin while true do begin MessageBox(0,'1','',MB_OK); if bActive_ then begin end; MessageBox(0,'2','',MB_OK); end; end; end. >Bist Du sicher, Du weisst, was (Delphi)Klassen sind bzw. wie man damit arbeitet? Oder ist das nur die übliche ouch! Betriebsblindheit? Bitte nicht nur bei den anderen nach Fehlern suchen. MfG Mega. |
Re: Problem mit Thread in der Klasse
Was alzaimar da jetzt meinte, habe ich auch nicht so ganz verstanden. Jedenfalls kann man Klassenmethoden einer Klasse auch aufrufen ohne die zugehörige Klasse zu instanzieren. Dann kann man natürlich nicht auf andere Methoden oder Attribute der Klasse zugreifen, da sie ja nicht existieren, die Klasse wurde ja nicht instanziert und existiert im Speicher nicht. Eventuell meinte alzaimar das. Aber das machst du doch gar nicht, wenn ich das richtig sehe.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:16 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz