AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TThread.Queue - Datenübergabe

Ein Thema von Hobbycoder · begonnen am 5. Mai 2020 · letzter Beitrag vom 5. Mai 2020
Antwort Antwort
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#1

AW: TThread.Queue - Datenübergabe

  Alt 5. Mai 2020, 13:42
Leider ist das bei mir noch nicht so ganz angekommen.

Heißt das jetzt, dass ich das mit einer Queue gar nicht machen kann? Ich hab noch nicht so ganz raus, wie das mit den Queues funktioniert.

In meinem Fall beinhaltet die Userlist die Daten hinter meinem VirtualListView. Für eine Aktualisierung lass ich alles Zeitaufwendige vom Thread erledigen, und erst wenn alles fertig bereit im Speicher liegt, übergebe ich die Daten an meine Userlist der Form und aktualisiere dann mein Virtuallistview.
Ich hatte mir das so vorgestellt, die UserList vom Thread an die Queue des MainThreads zu übergeben, und dann, wenn der Mainthread mal zeit hat, kann er ja die Aktualisierung vornehmen. Der Thread soll jetzt aber nicht darauf warten müssen (so wie es ja zur Zeit durch das Synchronize ist).

Logischerweise, da TThread.Queue ja asynchron arbeitet, wären natürlich die Daten aus dem Thread gar nicht mehr da, wenn der Mainthread sich endlich damit befassen könnte. Mein Gedanke war jetzt, dass man der Queue auch Daten mitgeben könnte, die sie quasi nur diese eine Prozedur behält, und danach verwirft.
(Klingt ein bisschen bescheuert, wie ich mich jetzt ausgedrückt habe).

Wenn ich dich also richtig verstehe, dann taugt eine Queue quasi nur als "Signalgeber" bzw. Trigger für irgendwas "datenloses".

Oder anders ausgedrückt. Ich erstelle mir im Hauptthread nehmen meiner UserList eine zweite Instanz, die aber nur für den Thread da ist. Diese zweite Instanz wird vom Thread mit Daten gefüllt, und über eine Queue teile ich dem Hauptthread nur mit "Bin fertig". Danach kann der Hauptthread mit zweiten Instanz machen was er will.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.665 Beiträge
 
Delphi 12 Athens
 
#2

AW: TThread.Queue - Datenübergabe

  Alt 5. Mai 2020, 13:54
Das Problem hier ist eher deine UserList-Instanz, die du der Queue irgendwie mitgeben willst. Queue blockt ja nicht und der darauf folgende Thread-Code wird quasi direkt nach dem Aufruf ausgeführt. Dieser gibt in deinem Fall als erstes die UserList frei, was zu einem Fehler im Hauptthread führt.

Mit einem temporären String kann man das aber lösen:
Delphi-Quellcode:
procedure TSQLGetUser.DoUpdateUserList(UserList: TUserList);
var
  tmpString: string;
begin
  if Assigned(FOnUpdateUserList) then
  begin
    tmpString := UserList.CommaText;
    TThread.Queue(nil,
      procedure
      var
        tmpList: TStringList;
      begin
        tmpList := TStringList.Create;
        try
          tmpList.CommaText := tmpString;
          FOnUpdateUserList(Self, tmpList);
        finally
          tmpList.Free;
        end;
      end);
  end;
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#3

AW: TThread.Queue - Datenübergabe

  Alt 5. Mai 2020, 14:09
Das Problem hier ist eher deine UserList-Instanz, die du der Queue irgendwie mitgeben willst. Queue blockt ja nicht und der darauf folgende Thread-Code wird quasi direkt nach dem Aufruf ausgeführt. Dieser gibt in deinem Fall als erstes die UserList frei, was zu einem Fehler im Hauptthread führt.

Mit einem temporären String kann man das aber lösen:
Delphi-Quellcode:
procedure TSQLGetUser.DoUpdateUserList(UserList: TUserList);
var
  tmpString: string;
begin
  if Assigned(FOnUpdateUserList) then
  begin
    tmpString := UserList.CommaText;
    TThread.Queue(nil,
      procedure
      var
        tmpList: TStringList;
      begin
        tmpList := TStringList.Create;
        try
          tmpList.CommaText := tmpString;
          FOnUpdateUserList(Self, tmpList);
        finally
          tmpList.Free;
        end;
      end);
  end;
end;
Okay, nun sind meine benötigten Daten doch etwas umfangreicher als eine StringList. Aber was mit einer StringList geht, geht auch mit einer TObjectList;

Also müsste das ja äquivalent funktionieren:
Delphi-Quellcode:
procedure TSQLGetUser.DoUpdateUserList(UserList: TUserList);
var
  MyUserList: TUserList;
begin
  if Assigned(FOnUpdateUserList) then
  begin
    MyUserList:=TUserList.Create(True);
    Try
      UserList.AssignTo(MyUserlist);
      TThread.Queue(nil,
        procedure
        var
          QUserList: TUseList;
        begin
          QUserList:= TUseList.Create(True);
          try
            MyUserlist.AssignTo(QUserList);
            FOnUpdateUserList(Self, QUserList);
          finally
            QUserList.Free;
          end;
        end);
    Finally
      MyUserList.Free;
    end;
  end;
end;
Okay, die Methode ist anonym. Aber zu welchem Zeitpunkt wird sie ausgeführt? Die Daten werden ja erst innerhalb der anonymen Methode zugewiesen (ist in deinem Beispiel mit der TStringlist ja auch so). Ich nahm jetzt aber an, dass die Queue des Hauptthread selber entscheidet, wann die Methode ausgeführt wird. Und das könnt ja dann auch wieder sein, wenn die Daten (in meinem Beispiel MyUserList) bereits wieder zerstört sind.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.665 Beiträge
 
Delphi 12 Athens
 
#4

AW: TThread.Queue - Datenübergabe

  Alt 5. Mai 2020, 14:36
Nein, das funktioniert eben nur deswegen mit TStrings, weil die Übergabe von einem Thread auf den anderen mit einem String erfolgt. Durch die implizite Referenzzählung bei Strings erfolgt die Freigabe erst dann, wenn der String nicht mehr gebraucht wird.

Wenn du Objekt-Instanzen übergeben willst, musst du dir über die Ownership klar werden. Du kannst eine Transport-Instanz des Objekts erzeugen und diese dann in der anonymen Methode freigeben:
Delphi-Quellcode:
procedure TSQLGetUser.DoUpdateUserList(UserList: TUserList);
var
  MyUserList: TUserList;
begin
  if Assigned(FOnUpdateUserList) then
  begin
    MyUserList:=TUserList.Create(True);
    UserList.AssignTo(MyUserlist);
    TThread.Queue(nil,
      procedure
      begin
        try
          FOnUpdateUserList(Self, MyUserList);
        finally
          MyUserList.Free;
        end;
      end);
  end;
end;
Es wäre auch interessant zu sehen, was in AssignTo gemacht wird.

Abgesehen davon ist gewinnt dein Beispiel nicht wirklich durch Queue. Da nach dem Synchronize eh nur noch aufgeräumt wird, bringt eine Nebenläufigkeit hier gar nicht so viel.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#5

AW: TThread.Queue - Datenübergabe

  Alt 5. Mai 2020, 14:47
Ah, das mit der implizite Referenzzählung bei Strings wusste ich gar nicht

Mein AssignTo ist ganz Trivial:
Delphi-Quellcode:
procedure TUser.AssignTo(Dest: TObject);
begin
  if Dest is TUser then
  begin
    (Dest as TUser).guid:=Self.Fguid;
    (Dest as TUser).Name:=Self.FName;
    (Dest as TUser).LoggedOn:=Self.FLoggedOn;
    (Dest as TUser).Calls:=Self.FCalls;
    (Dest as TUser).Sales:=Self.FSales;
  end;
end;
Abgesehen davon ist gewinnt dein Beispiel nicht wirklich durch Queue. Da nach dem Synchronize eh nur noch aufgeräumt wird, bringt eine Nebenläufigkeit hier gar nicht so viel.
Es gibt natürlich auch noch Threads, die nicht nur simple Dinge tun, eine längere Laufzeit und auch eine längere Lebensdauer haben. Wo Daten auch mal zwischendurch übergeben werden.
Im Grunde bin ich irgendwo über TThread.Queue gestolpert, und will mir die Funktionweise und Anwendungsmöglichkeiten verdeutlichen bzw. sie dann für mich nutzen.

Soweit funktioniert das mit meinen Events alles so wie ich es möchte, aber vielleicht kann ich es ja auch besser machen.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:41 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