![]() |
Parameterübergabe bei BeginThread für Klassenmethode
Ich habe im Moment eine threoretische Fragen, bei der ich nicht ganz verstehe, warum es denn nicht klappt. Und zwar kann ich via
Delphi-Quellcode:
ja den Code einer Procedure als Thread ausführen -- das ganze klappt auch wunderbar mit einer Klassenmethode. Nun wollte ich auf Self als Parameter übergeben, was ich auch via [delphi]Pointer(Self)[/delphi) getan habe.
BeginThread()
Wenn ich nun eine Klassenmethode via BeginThread ausführe, so bekomme ich es nicht gebacken, Self über den Parameter zu erhalten. Habe ich statt dessen eine (globale) Procedure als Thread-Code, so funktioniert die Übergabe von Self ohne Probleme. Nur warum ist das so? Ich habe in einem Post vorher gelesen, dass das nur so klappt, nur stand da leider keinerlei Begründung. Hier nochmal etwas Code:
Delphi-Quellcode:
type
TTest = class(TObject) private FThreadHandle : Integer; FThreadID : Cardinal; public procedure StartIt(); procedure ThreadedMethod(Instance: TTest); end; procedure ThreadedProcedure(Instance: TTest); implementation // --- here the global procedure --- procedure ThreadedProcedure(Instance: TTest); begin // // < ------- Instance = Self parameter // end; // --- here the class methods --- procedure TTest.StartIt(); begin // i know, i overwrite the handle and id ;) FThreadHandle := BeginThread(nil, 0, @ThreadedProcedure, Pointer(Self), 0, FThreadID); FThreadHandle := BeginThread(nil, 0, @TTest.ThreadedMethod, Pointer(Self), 0, FThreadID); end; procedure TTest.ThreadedMethod(Instance: TTest); begin // // < ------- Instance <> Self parameter // end; |
AW: Parameterübergabe bei BeginThread für Klassenmethode
Das ist ganz einfach.
Deine Methode TTest.ThreadedMethod sieht intern so aus:
Delphi-Quellcode:
Es gibt also immer als ersten Parameter den unsichtbaren Self-Parameter. Anders ausgedrückt heißt es das deine Methode incompatibel zur erwarteten Funktion ist die eben nur einen Parameter vom Typ Pointer hat. Man sollte sich aber auch nicht darauf verlassen das es in alle Ewigkeit so aussieht das der erste unsichtbare Parameter Self ist. Denn wenn irgendwann mal in einer neuen Version oder bei einem anderen Compiler das ganze intern anders gehandhabt wird funktionieren dann solche hacks nicht mehr:
procedure TTest.ThreadedMethod(Self: TTest; Instance: TTest);
Delphi-Quellcode:
(also das man eine Parameterlose Methode nimmt wohlwissen das der unsichtbare Parameter Self der einzige ist.
procedure TTest.ThreadedMethod();
|
AW: Parameterübergabe bei BeginThread für Klassenmethode
oder als statische Klassenmethode:
Delphi-Quellcode:
.
class procedure ThreadedMethod(Instance: TTest); static;
Methoden und "nicht-statische" Klassen-Methoden haben eben dieses unsichtbare "Self" mit drin. > Methode: Self=Objektinstanz > Klassen-Methode: Self=Klassen-Typ > statische (static) Klassen-Methode: Self gibt's nicht |
AW: Parameterübergabe bei BeginThread für Klassenmethode
@himitsu? Bist du sicher das es so funktioniert? Ich hab mir den ASM-Code nicht angesehen aber kann es nicht sein das auch bei Klassenmethoden der unsichtbare Self-Parameter existiert? Nur eben nicht als Instanz sondern der Klasse selbst.
[Edit] @himitus: Hätte ich deinen Beitrag mal zu Ende gelesen so hätte ich mir diesen Beitrag im gesamten hier sparen können :oops: |
AW: Parameterübergabe bei BeginThread für Klassenmethode
@SirThornberry:
Hat er doch geschrieben?! :-D |
AW: Parameterübergabe bei BeginThread für Klassenmethode
Zitat:
|
AW: Parameterübergabe bei BeginThread für Klassenmethode
Das ist bei Delphi eigentlich schon immer so, also daß Klassen-Methoden diesen unsichtbaren Parameter haben.
Irgendwo muß je die Information herkommen, um welche Klasse/Instanz es sich handelt, wenn man eine Methode aufruft. Der TMethod-Zeiger ist auch um diesen Parameter größer. (Zeiger auf Methode + die Objektinstanz) |
AW: Parameterübergabe bei BeginThread für Klassenmethode
Nur habe ich diese Information immer nur aus dem DP-Forum. An offizieller Stelle habe ich das noch nie gesehen.
|
AW: Parameterübergabe bei BeginThread für Klassenmethode
Offiziell steh halt einiges nirgends.
z.B. sieht
Delphi-Quellcode:
intern eigentlich so aus
function test: String;
Delphi-Quellcode:
Bei einem Integer sieht es aber anders aus.
procedure test(var Result: String);
Ihr könnt ja gerne mal raten, welche Werte von den Messageboxen angezeigt werden ... mal sehn wer alles richtig tippt. :angel:
Delphi-Quellcode:
PS: Das ist auch ein gutes Beispiel, warum meistens Variablenwerte immer initialisiert werden sollten.
function Test: String;
begin Result := Result + 'abc '; raise Exception.Create('buhh'); end; function Test2: String; begin Result := Result + 'abc '; end; function Test3: Integer; begin Result := 1; raise Exception.Create('buhh'); end; function Test4: Integer; begin Result := Result + 1; end; procedure TForm1.FormCreate(Sender: TObject); var S: String; i: Integer; begin try S := Test; except // heut ma nix end; ShowMessage(S); S := 'tja '; S := Test2; S := Test2; ShowMessage(S); try i := Test3; except // heut ma nix end; ShowMessage(IntToStr(i)); i := 10; i := Test4; i := Test4; ShowMessage(IntToStr(i)); end; |
AW: Parameterübergabe bei BeginThread für Klassenmethode
Zitat:
Wie sieht es eigentlich mit der Aufrufkonvention aus? Ist BeginThread eine Api-Funktion? Wenn ja wird doch sicher stdcall oder cdecl erwartet oder? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:52 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