![]() |
Delphi-Version: 5
Anonymous method: TProc Referenzen vergleichen
Hallo zusammen,
ich möchte eine Funktion wie hier mehrfach aufrufen
Delphi-Quellcode:
Dazu müsste ich an einer Stelle zwei Referenzen zu anonymen Methoden vergleichen,
procedure CalledByButtonClick;
begin // Beim Eintritt soll gecheckt werden ob die Funktion noch läuft // wenn ja, wird die alte Funktion gekillt und ersetzt TAnonCaller.ExecuteWithKillAndDelay(procedure begin // Kommt hier nach Verzögerung an end); end; ungefähr so:
Delphi-Quellcode:
Ich habe schon einiges Interessantes dazu gefunden// A1 ist die Referenz auf die intern gespeicherte anonyme prozedur, s.o, // A2 ist die Referenz auf (dieselbe) anonyme prozedur, nur eben wir diese jetzt zum 2. Mal aufgerufen function Compare(A1 : TProc; A2 TProc) : Boolean; begin Result := A1 = A2; end; ![]() ![]() ![]() ![]() ![]() Aber so richtig weiter komme ich im Moment damit nicht. Der bisher vielversprechendste Ansatz war der:
Delphi-Quellcode:
So kann ich die Typen von P1 analysieren, aber eben nicht herausfinden ob P1 = P2 ist.
procedure Test(P1 : TProc; P2 : TProc);
type PIInterface = ^IInterface; var UnitName : String; Ctx: TRttiContext; ProcType: TRttiType; obj1: TInterfacedObject; begin obj1 := PIInterface(@P1)^ as TInterfacedObject; UnitName := obj.UnitName; Ctx := TRttiContext.Create; ProcType := Ctx.GetType(obj1.ClassType); Vielleicht könnte mich freundlicherweise jemand in die richtige Richtung schubsen, denn wahrscheinlich sehe gerade ich den Wald vor lauter Bäumen nicht mehr :stupid: Rollo |
AW: Anonymous method: TProc Referenzen vergleichen
Eventuell verstehe ich Dich ja falsch.
Nach meinem Verständnis sind anonyme Methoden nie gleich ausser Du hälst Sie in einer Variablen, also so was wie:
Delphi-Quellcode:
var Proc1 : Tproc;
Proc2 : Tproc begin Proc1 := procedure begin tuewas; end; Proc2 := Proc1; end; |
AW: Anonymous method: TProc Referenzen vergleichen
Ja ich halte die in einer Variablen.
Und wenn ich die Eintrittfunktion nochmal aufrufe möchte ich vergleichen ob die Gleiche Variable schon drin ist. Weil das Asynchron läuft kann die Eintrittfunktion zweimal aufgerufen werden, so das die Bearbeitung intern noch gar nicht die TProc aufgerufen hat. Ich könnte jetzt natürlich zusätzliche Variablen drumrum bauen, aber eigentlich reicht mir die TProc Variable, und die möchte ich dafür vergleichen mit der neuen Eintrittsfunktion. Rolf |
AW: Anonymous method: TProc Referenzen vergleichen
Habe mal einen kleinen test gebaut:
Delphi-Quellcode:
Da sieht man schön das test2refernce funktioniert.
unit testProc;
interface uses System.Sysutils, DUnitX.TestFramework; type [TestFixture] TestTproc = class(TObject) private function GetProc(const Value : integer): TProc; public [TEST] procedure test2vars; [TEST] procedure test2refernce; end; implementation { TestTproc } type PIInterface = ^IInterface; function TestTproc.GetProc(const Value : integer): TProc; begin result := procedure Var x : integer; begin x := 2 * Value; if x > 3 then; end; end; procedure TestTproc.test2vars; var lp1, lp2 : Tproc; obj1, obj2: TInterfacedObject; begin lp1 := GetProc(1); lp2 := GetProc(1); assert.AreNotEqual<Tproc>(lp1, lp2); obj1 := PIInterface(@lp1)^ as TInterfacedObject; obj2 := PIInterface(@lp2)^ as TInterfacedObject; // Will fail.... assert.AreEqual<TInterfacedObject>(obj1, obj2); end; procedure TestTproc.test2refernce; var lp1, lp2 : Tproc; obj1, obj2: TInterfacedObject; begin lp1 := GetProc(1); lp2 := lp1; assert.AreEqual<Tproc>(lp1, lp2); obj1 := PIInterface(@lp1)^ as TInterfacedObject; obj2 := PIInterface(@lp2)^ as TInterfacedObject; assert.AreEqual<TInterfacedObject>(obj1, obj2); end; initialization TDUnitX.RegisterTestFixture(TestTproc); end. |
AW: Anonymous method: TProc Referenzen vergleichen
Die Zeiger kannst du vergleichen, daber wenn du jedes Mal eine neue anonyme Methode genierierst, dann haben die Alle auch immer einen unterschiedlichen Zeiger.
Also zwei TProc lassen sich problemlos vergleichen, aber nur wenn du am Anfang auch einmal aus deiner Procedure eine TProc machst. (siehe Post #2, nur die Variable halt globaler speichern) TProc ist intern ein Interface, aber leider wird das Objekt dazu dynamisch gebaut, also Anhand des zugewiesenen Prozedur/Methoden-Typen hat das Objekt unterschiedlichen Speicher und da dafür auch keine RTTI generiert wird, kann man den Inhalt leider nicht auslesen, da man nicht weiß was man da eigentlich liest (Methode/ClassMethode, StaticMethode/ReguläreProcedur oder sone eingebettete Anonyme ... den Speicher zu analysieren macht keinen Spaß und ist auch nicht 100% sicher). |
AW: Anonymous method: TProc Referenzen vergleichen
Zitat:
Dankesehr für den Hinweis. Genau das war mir eben nicht ganz klar, ob der Kompiler das bei jedem Aufruf neu anlegt. Bei genauerer Überlegung muss er das aber eingenlich machen, denn es könnte ja ein Tread o.ä. diese Eintrittfunktion mehrfach aufrufen. Das interpretiere ich mal so, das dann alle Funktionen jeweils ihren eigenen Scope haben müssen. Dann dürfte sich auch nichts ändern wenn man in der Eintrittsfunktion "const" verwendet ?
Delphi-Quellcode:
Weil trotzdem jeder Aufruf der Eintrittsfunktion einen neuen Scope erzeugen muss, richtig ?
procedure TAnonCaller.ExecuteWithKillAndDelay([B]const [/B]AProc : TProc);
begin ... Schade, dann muss ich mir da irgendwas drumrum bauen. Edit: Ich habe es übrigens bisher so gemacht das mir die Eintrittfunktion eine eindeutige ID zurückliefert. Diese muss ich dan ausserhalb der TAnonCaller Klasser verwalten, das hätte ich aber gerne von innen gemacht. Rollo |
AW: Anonymous method: TProc Referenzen vergleichen
Hallo,
geht es hier jetzt speziell um anonyme Funktionen oder eher um den asynchronen Aufruf, also um Thread-Synchronisation? Wenn Du wirklich die Methode killen willst, würde ich einen Thread benutzen, wenn es um die Verhinderung des doppelten Aufrufes geht, dann mit Hilfe der Synchronisations-Objekte, z.B. TCriticalSection. |
AW: Anonymous method: TProc Referenzen vergleichen
Es geht eher um die anonymen Methoden.
Die TAnonCaller macht gewisse Dinge intern, die ich bei einem vorzeitigen zweiten Aufruf abbrechen möchte. Da hilft mir ein Thread nicht unbedingt weiter, denn mir fehlt ja die Referenz auf den Caller, das ist mein Problem damit. Denn ohne diese Referenz kann ich nicht eindeutig sagen "welchen" Caller ich abbrechen soll, und diese Referenzen scheinen ja bei jedem Aufruf intern neu angelegt zu werden. Eine Möglichkeit wäre vielleicht dem Caller einfach den Sender mitzugeben, und diesen dann intern mitzuverwalten (was ich zwar nicht so ideal finde, aber womöglich gar nicht anders geht).
Delphi-Quellcode:
Rollo
procedure TAnonCaller.ExecuteWithKillAndDelay(Sender : TObject; AProc : TProc);
begin ... |
AW: Anonymous method: TProc Referenzen vergleichen
Zitat:
Und bedenke auch, dass hier diese Methode auch auf lokale Variablen zugreifen könnte, das ist noch ein Grund, warum das bei jedem Aufruf neu sein muß. Wie gesagt, man könnte zwar in Ausnahmefällen prüfen ob die internen Zeiger gleich sind, aber hier würde auch der Scope z.B. auf lokale Variablen sich sowieso unterscheiden, selbst wenn die Code-Adresse der Methode gleich wäre. Da sich die Position des Methoden-Zeigers innherhalb des internen InterfacesObjekts nicht fest ist, lässt dieses sich halt schwer vergleichen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:38 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