Einzelnen Beitrag anzeigen

Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#1

Auto-Vervollständigung und anonyme Prozeduren

  Alt 13. Mär 2021, 15:44
Hallo zusammen,

Ich habe gerade folgendes Problem, das mich etwas stört: In einer Unit mit einer Thread-Klasse mache ich aus dem Thread heraus einen Callback in den Main-Thread mittels TThread.Queue. Das Ganze sieht folgendermaßen aus:

Delphi-Quellcode:
procedure TMyThread.Run;
var
  airplanes: IAirplanes;
begin
  airplanes := ...;
  ...
  TThread.Queue(self, procedure
                      begin
                        FCriticalSectionCallback.Enter;
                        try
                          if Assigned(FCallback) then
                            FCallback(airplanes);
                        finally
                          FCriticalSectionCallback.Leave;
                        end;
                      end);
end;
Die anonyme Prozedur führt dazu, die Auto-Vervollständigung von Delphi nicht mehr funktioniert. Wenn ich beispielsweise irgendwo ein "begin" schreibe und Enter drücke, wird kein "end" automatisch eingefügt, was ziemlich störend ist. Wenn ich den Inhalt der anonymen Prozedur leer mache, dann funktioniert es.

Weiß jemand, wie man das Problem vermeiden kann?

Ich habe es bereits mit der Deklaration einer Methode versucht. Problem ist hierbei allerdings, dass die Methode, die man als Parameter an TThread.Queue übergeben muss, selbst keinen Übergabeparameter haben darf (muss vom Typ "procedure of object" sein). Ich muss jedoch auf die lokale Variable "airplanes" zugreifen.

Während ich den Beitrag geschrieben habe, ist mir noch folgende Idee in den Kopf gekommen:
Delphi-Quellcode:
TMyThread = class(TThread)
strict private
  procedure ExecuteCallback;
  ...
end;

implementation

procedure TMyThread.ExecuteCallback(const Airplanes: IAirplanes);
begin
  FCriticalSectionCallback.Enter;
  try
    if Assigned(FCallback) then
      FCallback(Airplanes);
  finally
    FCriticalSectionCallback.Leave;
  end;
end;

procedure TMyThread.Run;
var
  airplanes: IAirplanes;
begin
  airplanes := ...;
  ...
  TThread.Queue(self, procedure
                      begin
                        ExecuteCallback(airplanes);
                      end);
end;
Auf diese Weise funktioniert die Auto-Vervollständigung allerdings leider auch nicht. Eine weitere Idee wäre, den Parameter "airplanes" vor dem Aufruf an TThread.Queue in einem Feld zu speichern und anstatt der anonymen Prozedur eine Methode zu erstellen, die wie ExecuteCallback implementiert ist, aber keinen Übergabeparameter hat, stattdessen auf das Feld zugreift. Da bin ich mir allerdings nicht sicher, ob das threadsafe ist, weil, die Methode Run mehrmals aufgerufen wird und ich nicht weiß, ob es einen Unterschied macht, ob die an TThread.Queue übergebene Prozedur zum Zeitpunkt des zweiten Aufrufs schon ausgeführt wurde oder nicht. Ich möchte sicher sein, dass der jeweils gesetzte Wert von airplanes verwendet wird. Bei der Verwendung eines Feldes sehe ich da zumindest eine mögliche Fehlerquelle.

Hat jemand eine Lösung?
  Mit Zitat antworten Zitat