Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Callback mit Übergabe von Objekten (https://www.delphipraxis.net/202726-callback-mit-uebergabe-von-objekten.html)

Ykcim 2. Dez 2019 16:53

Callback mit Übergabe von Objekten
 
Hallo Zusammen,

das Thema CallBack ist für mich neu und ich stehe gerade völlig auf dem Schlauch...


Ich möchte etwas ausprobieren. Dazu rufe ich einen Service auf dem Server auf, der mir eine Datenmenge aus der Datenbank zurückliefert. Diese Daten werden in ein TWebStringGrid (TMS) geladen. Dort sollen sie rausgeholt und in ein TTMSFNCGrid (TMS) geschrieben werden. Weil ich ja warten muss, bis die Daten auch wirklich übermittelt wurden, wollte ich das mit einer CallBack Procedure machen.

Das ist mein Versuch (ich bin mir ziemlich sicher, dass ich das Zusammenspiel hier falsch mache...)
Das ist der Aufruf
Delphi-Quellcode:
procedure TLogic.Get_Beobachtete_FA(Sender: TObject);
var
   URL: string;
begin
   URL:=Data_Module.xConnection.url;
   URL:=URL+'Data_xChangeService/Get_BeobachteteFAs';
   URL:=URL+'?User_ID=';
   URL:=URL+Data_Module.xDST_User.FieldByName('UserID').AsString;
   Data_Module.Get_Grid_Data(URL, (Sender as TTMSFNCGrid), WebGrid_FNCGrid());
end;
Hier werden die Daten erst einmal in das TWebStringGrid geladen
Delphi-Quellcode:
type
   TConnectCallback = reference to procedure;
   TDataRecievedCallback = reference to procedure;

...

procedure TData_Module.Get_Grid_Data (URL: string; FNCGrid: TTMSFNCGrid; AOnDataRecieved: TDataRecievedCallback);
var
   WGrid: TWebStringGrid;
begin
   WGrid:= TWebStringGrid.Create(nil);
   Try
      WGrid.LoadFromJSON(URL);
      if Assigned(AOnDataRecieved) then begin
         AOnDataRecieved(WGrid, FNCGrid);
      end;
   Finally
      //WGrid.Free;
   End;
end;
Wenn die Daten im TWebStringGrid sind, soll die AOnDataReceived aufgerufen werden. Das ist die procedure WebGrid_FNCGrid.
Delphi-Quellcode:
procedure TLogic.WebGrid_FNCGrid(WGrid: TWebStringGrid;
  FNCGrid: TTMSFNCGrid);
var
   I, J: integer;
begin
   FNCGrid.Columns.Count:=WGrid.ColCount;
   FNCGrid.RowCount:=Wgrid.RowCount;
   for I := 0 to WGrid.RowCount -1 do begin
      for J := 0 to WGrid.ColCount -1 do begin
         FNCGrid.Cells[J,I]:=WGrid.Cells[J,I];
      end;
   end;
end;
Aber egal wie rum ich es auch ausprobiere (das ist jetzt gerade nur der aktuelle Stand), ich bekomme es nicht ans Laufen...

Hehlermeldung:
Zitat:

[Fehler] TLogicUnit.pas(38): Wrong number of parameters specified for call to "procedure WebGrid_FNCGrid(TStringGrid;TTMSFNCGrid) of Object"
Kann mir jemand einen Tip geben?

Vielen Dank
Patrick

himitsu 2. Dez 2019 17:34

AW: Callback mit Übergabe von Objekten
 
Stimmt doch, diese Fehlermeldung. :)

Du hast einen Zeiger-Typen mit 0 Parametern
Delphi-Quellcode:
TDataRecievedCallback = reference to procedure;
aka
Delphi-Quellcode:
TDataRecievedCallback = reference to procedure();


und versucht aber 2 Parameter zu übergeben
Delphi-Quellcode:
AOnDataRecieved(WGrid, FNCGrid);


Lösung:
ohne Parameter aufrufen
Delphi-Quellcode:
AOnDataRecieved();
:zwinker:
oder
Delphi-Quellcode:
TDataRecievedCallback = reference to procedure(WGrid: TWebStringGrid; FNCGrid: TTMSFNCGrid);

Incocnito 3. Dez 2019 07:10

AW: Callback mit Übergabe von Objekten
 
Ich weiß nicht, ob ich dafür nun extra einen neuen Thread aufmachen sollte, aber ich hoffe das geht auch so ...

Ich kenne das bisher nur, dass man Funktions-Typen so schreibt:
Delphi-Quellcode:
type TMyProc = Procedure();
evtl. noch
Delphi-Quellcode:
type TMyProc = Procedure() of object;
oder bei Parametern
Delphi-Quellcode:
type TMyProc = Procedure(const bValue : Boolean) of object;
aber
Delphi-Quellcode:
type TMyProc = reference to procedure();

habe ich in dem Zusammenhang noch nie gesehen.
Kann das einer in ein/zwei Sätzen erklären was es mit "reference to" auf sich hat
oder weiß einer eine Seite, die das so erklärt,
dass es ein 6-jähriger Versteht? :wink:

---------------

Um vielleicht doch noch was "produktives" beizutragen:
Im Prozedur-Header steht:
Delphi-Quellcode:
procedure TLogic.WebGrid_FNCGrid(WGrid: TWebStringGrid; FNCGrid: TTMSFNCGrid);
in der Fehlermeldung
Delphi-Quellcode:
procedure WebGrid_FNCGrid(TStringGrid;TTMSFNCGrid) of Object;
Evtl. Ist TWebStringGrid nicht vom TStringGrid geerbt?
TMS hatte (wenn ich mich recht erinnere)ceine andere "Oberklasse".
... Ist mir nur aufgefallen, muss nichts heißen!

MfG
Incocnito

freimatz 3. Dez 2019 07:59

AW: Callback mit Übergabe von Objekten
 
Reicht auch ein 10-jähriger? :-P
Wenn Du weisst was eine eierlegende Wollmilchsau ist - "reference to" ist so was. Nehm die, dann brauchst du dir um die Varianten in den meisten Fällen keinen Kopf mehr machen.

Rollo62 3. Dez 2019 08:45

AW: Callback mit Übergabe von Objekten
 
Vielleicht das als Hilfestellung.

himitsu 3. Dez 2019 10:07

AW: Callback mit Übergabe von Objekten
 
Ein eigener Thread wäre besser, wenn du es genauer wissen willst.
Delphi-Quellcode:
type TMyProc = procedure(...); // Zeiger auf normale Prozedur oder statische Klassen-Methode
type TMyProc = procedure(...) of object; // Zeiger auf Methode oder Klassen-Methode
type TMyProc = reference to procedure(...); // Zeiger auf Alles: anonyme Methode oder die Anderen
Werden Referenzzeiger neu zugewiesen, dann bekommen sie immer wieder ein neues Interface. Sie lassen sich also nur prüfen auf Assigned und nil oder vergleichen mit einem anderem Referenzzeiger (der sich zwischen Zuweisung an den eigenen Zeiger und dem Vergleich nicht verändert hat).

Ykcim 3. Dez 2019 10:09

AW: Callback mit Übergabe von Objekten
 
Hallo Zusammen,

vielen Dank für die Unterstützung. Ich habe es jetzt soweit geschafft, dass ich das Projekt wieder kompilieren kann... :wink:

Aber leider scheinen die Procedure in seltsamer Reihenfolge ausgeführt zu werden.
Ich habe jetzt Folgendes gemacht:
Delphi-Quellcode:
type
   TConnectCallback = reference to procedure;
   TDataRecievedCallback = reference to procedure;
   TGridDataRecievedCallback = reference to procedure(WGrid: TWebStringGrid; FNCGrid: TTMSFNCGrid);
Als erstes noch einen passende Typen hinzugefügt.

Delphi-Quellcode:
procedure TLogic.Get_Beobachtete_FA(Sender: TObject);
var
   URL: string;
   WGrid: TWebStringGrid;
begin
   URL:=Data_Module.xConnection.url;
   URL:=URL+'Data_xChangeService/Get_BeobachteteFAs';
   URL:=URL+'?User_ID=';
   URL:=URL+Data_Module.xDST_User.FieldByName('UserID').AsString;
   ShowMessage('1)'+URL);
   WGrid:= TWebStringGrid.Create(nil);
   Try
      Data_Module.Get_Grid_Data(URL, WGrid, (Sender as TTMSFNCGrid), WebGrid_FNCGrid(WGrid, (Sender as TTMSFNCGrid)));
   Finally
      //WGrid.Free;
   End;
end;
Das ist der Aufruf (Data_Module.Get_Grid_Data) und diesem wird die Callback-Procedure WebGrid_FNCGrid(WGrid, (Sender as TTMSFNCGrid)) mitgegeben.

Delphi-Quellcode:
procedure TData_Module.Get_Grid_Data (URL: string; WGrid: TWebStringGrid; FNCGrid: TTMSFNCGrid; AOnGridDataRecieved: TGridDataRecievedCallback);
begin
   ShowMessage('2) Get_Grid_Data');
   Try
      WGrid.LoadFromJSON(URL);
      if Assigned(AOnGridDataRecieved) then begin
         AOnGridDataRecieved(WGrid, FNCGrid);
      end;
   Finally
      //WGrid.Free;
   End;
end;
Hier ist der Code von Get_Grid_Data.

Delphi-Quellcode:
procedure TLogic.WebGrid_FNCGrid(WGrid: TWebStringGrid;
  FNCGrid: TTMSFNCGrid);
var
   I, J: integer;
begin
   Showmessage('3)'+IntToStr(FNCGrid.ColumnCount)+' / '+IntToStr(WGrid.ColCount));
   FNCGrid.ColumnCount:=WGrid.ColCount;
   FNCGrid.RowCount:=Wgrid.RowCount;

   for I := 0 to WGrid.RowCount -1 do begin
      for J := 0 to WGrid.ColCount -1 do begin
         Showmessage(IntToStr(J)+' / '+IntToStr(I)+' / '+WGrid.Cells[J,I]);
         FNCGrid.Cells[J,I]:=WGrid.Cells[J,I];
      end;
   end;
   //Design.GridDesign(FNCGrid);
end;
Und schließlich der Code der CallBack Procedure...

Mir fiel auf, dass obwohl die Callback-Funktion aufgerufen wird, keine Daten in dem TWebStringGrid waren...
Ich habe ein paar ShowMeassges gesetzt. Ich hatte erwartet, dass erst
Delphi-Quellcode:
ShowMessage('1)'+URL);
aus Get_Beobachten, dann
Delphi-Quellcode:
ShowMessage('2) Get_Grid_Data');
aus Get_Grid_Data und zum Schluss
Delphi-Quellcode:
Showmessage('3)'+IntToStr(FNCGrid.ColumnCount)+' / '+IntToStr(WGrid.ColCount));
aus der CallBack Procedure WebGrid_FNCGrid angezeigt würde.
Aber zusehen bekomme ich nur 1 und 3, die 2 wird nicht angezeigt...

Kann mir jemand helfen, dass zu verstehen?

Vielen Dank
Patrick

himitsu 3. Dez 2019 11:26

AW: Callback mit Übergabe von Objekten
 
Gibt es im TWebStringGrid noch eine andere Version von Get_Grid_Data? (overload)

Zitat:

Delphi-Quellcode:
Data_Module.Get_Grid_Data(URL, WGrid, (Sender as TTMSFNCGrid), WebGrid_FNCGrid(WGrid, (Sender as TTMSFNCGrid)));

Dieser Aufruf kann eigentlich nicht stimmen. (ich würde erwarten, dass dort auch der Compiler meckert)

Du willst ja den Funktionszeiger übergeben, aber dort nicht die Funktion aufrufen und deren Result übergeben:
Delphi-Quellcode:
Data_Module.Get_Grid_Data(URL, WGrid, (Sender as TTMSFNCGrid), @WebGrid_FNCGrid);

oder meistens auch direkt so:
Delphi-Quellcode:
Data_Module.Get_Grid_Data(URL, WGrid, (Sender as TTMSFNCGrid), WebGrid_FNCGrid);

Wobei das @ hier implizit ist, also da der Parameter dieser Zeigertyp ist, weiß Delphi, dass du nicht aufrufen, sondern den Zeiger reingeben willst.

Ykcim 3. Dez 2019 12:56

AW: Callback mit Übergabe von Objekten
 
Hi Himitsu,

vielen Dank für Deine Unterstützung. Jetzt läuft die Abfolge korrekt.
Leider ist das Ergebnis aber noch nicht das, was ich gerne erreichen wollte. Ziel war es, dass die Callback-Procedure erst aufgerufen wird, wenn die Daten im TWebStringGrid angekommen sind. Jetzt scheint es so zu sein, dass die Daten noch nicht da sind, aber die Callback schon ausgeführt wird.

Wie kann ich das lösen?

Vielen Dank
Patrick


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:30 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz