AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

VirtualStringTree in Thread

Ein Thema von Zodi · begonnen am 28. Jun 2020 · letzter Beitrag vom 2. Jul 2020
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von Zodi
Zodi

Registriert seit: 19. Jul 2017
Ort: Berlin
45 Beiträge
 
Delphi XE7 Ultimate
 
#1

VirtualStringTree in Thread

  Alt 28. Jun 2020, 21:20
Hi Delphianer.

Ich habe folgendes Problem. Ich versuche meine VST in einem Thread zu füllen. Leider funktioniert das füllen nicht mehr
sobald ich es im Thread ausführe.
Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons,
  VirtualTrees, Vcl.ImgList;

type
  TForm2 = class(TForm)
    ImageList1: TImageList;
    VST: TVirtualStringTree;
    BitBtn1: TBitBtn;
    procedure BitBtn1Click(Sender: TObject);
    procedure VSTGetImageIndexEx(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex; var ImageList: TCustomImageList);
    procedure VSTGetNodeDataSize(Sender: TBaseVirtualTree;
    var NodeDataSize: Integer);
    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
      Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

type
  MyThread = class(TThread)
  private
    i:integer;
    { Private-Deklarationen }
  protected
    { protected-Deklarationen }
    procedure Execute; override;
    procedure DoSomething;
  public
    { Public-Deklarationen }
  end;

type
  PTreeData = ^TTreeData;
  TTreeData = packed record
  Column0: String; Column1: String; Column2: String;
end;

var
  MyThr: MyThread;
  Form2: TForm2;

implementation

{$R *.dfm}

procedure MyThread.Execute;
var
  Data: PTreeData;
  XNode: PVirtualNode;
  begin
 while not Terminated do
   begin
     inc(i);

   XNode := form2.VST.AddChild(nil);

   if form2.VST.AbsoluteIndex(XNode) > -1 then
     begin
       Data := form2.VST.GetNodeData(Xnode);
       Data^.Column0 := inttostr(i);
       Data^.Column1 := 'Wert 1';
       Data^.Column2 := 'Wert 2';
     end;

     if i = 10 then begin
        i:=0;
        SuspendThread(MyThr.Handle);
     end;

   Synchronize(DoSomething);
   end;
end;

procedure MyThread.DoSomething;
begin
//
end;

procedure TForm2.BitBtn1Click(Sender: TObject);
begin
       MyThr := MyThread.Create(True);
       MyThr.FreeOnTerminate := true;
       MyThr.Priority := tpIdle;
       ResumeThread(MyThr.Handle);
end;

procedure TForm2.VSTGetImageIndexEx(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex; var ImageList: TCustomImageList);
begin
  if Column = 0 then
    begin
      if Kind in [ikNormal, ikSelected] then ImageIndex := 0;
  end;

end;

procedure TForm2.VSTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
begin
  NodeDataSize := SizeOf(TTreeData);
end;

procedure TForm2.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  Data: PTreeData;
begin
  Data := VST.GetNodeData(Node);
  case Column of
    0: CellText := Data^.Column0;
    1: CellText := Data^.Column1;
    2: CellText := Data^.Column2;
  end;
end;

end.
Wenn ich aber im ButtonClick nicht den Tread starte sondern die VST direkt fülle.....
Delphi-Quellcode:
procedure TForm2.BitBtn1Click(Sender: TObject);
var
  Data: PTreeData;
  XNode: PVirtualNode;
begin
   XNode := VST.AddChild(nil);
   Data := VST.GetNodeData(Xnode);

   Data^.Column0 := inttostr(i);
   Data^.Column1 := 'Wert 1';
   Data^.Column2 := 'Wert 2';

end;
dann geht es was mache ich falsch?
Pascal
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
928 Beiträge
 
#2

AW: VirtualStringTree in Thread

  Alt 28. Jun 2020, 21:33
Du muss die Daten an den MainThread schicken und das Befüllen des VirtualStringTree auch im MainThread machen.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.610 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: VirtualStringTree in Thread

  Alt 28. Jun 2020, 22:53
Du hast eine Methodenaufruf Synchronize(DoSomething) im Code. Darin passiert aber gar nichts. Alles, was du mit dem VST machst, muss im Main Thread ausgeführt werden. Sprich, in die DoSomething() Methode rein.

Davon ab würde ich aber nur die Daten im Thread sammeln und das Befüllen des VST dem Hauptthread überlassen. Das Befüllen im Thread macht keinen Sinn, da du sowieso ständig mit dem Hauptthread synchronisieren musst.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.017 Beiträge
 
Delphi 12 Athens
 
#4

AW: VirtualStringTree in Thread

  Alt 29. Jun 2020, 00:18
Ich denke mal hier wird es auch gehn.

Bei der normalen TList kann man die auch im Thread befüllen, wenn man BeginUpdate nicht vergisst und damit den gleichzeigigen Refresh der GUI blockt.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Zodi
Zodi

Registriert seit: 19. Jul 2017
Ort: Berlin
45 Beiträge
 
Delphi XE7 Ultimate
 
#5

AW: VirtualStringTree in Thread

  Alt 1. Jul 2020, 23:43
Also ich habe jetzt wie mir oben empfohlen wurde den Befüllteil in's Synchronize geschoben.
Trotzdem funktioniert es nicht. was allerdings noch zu erwähnen ist, ist das ich ein Form1 und ein Form2 Formular habe.
Das Form2 soll mehrmals erzeugt werden.
Dies hab ich so Realisiert.
Delphi-Quellcode:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
 TestForm: TForm2;
begin
 TestForm := TForm2.Create(nil);
 TestForm.Show;
end;
Jedenfals wird so die VST nicht befüllt.

Wenn ich es allerding so mache dann geht es wobei dann nur 1 Formural angezeit wird.
Delphi-Quellcode:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
 TestForm.Show;
end;
Wo bin ich das auf dem Holzweg?
Pascal
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.610 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: VirtualStringTree in Thread

  Alt 2. Jul 2020, 00:20
Das sind etwas wenige Informationen zum Befüllen des VST. Wenn du damit Probleme hast, dann solltest du den SourceCode sinnvollerweise auch hier zeigen.

Ich rate jetzt einfach mal: Du gibst deinem Thread eine Referenz auf die Form2 mit. Diese Referenz ist aber die globale Variable im zweiten Formular und dementsprechend nicht richtig "befüllt". Hat also keine gültige Referenz. Du musst deinem Thread entweder die richtige Instanz deiner Form mitgeben oder - in meinen Augen - besser direkt über ein im Thread definiertes Event arbeiten.

Mehr kann ich ohne SourceCode aus meiner leider nicht herauslesen.

EDIT: Habe mir gerade nochmal den SourceCode aus deinem vorherigen Post angeschaut. Wenn der jetzt noch genau so aussieht, dann wird es wohl genau der Grund sein, den ich oben beschrieben habe, warum es nicht funktioniert.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.017 Beiträge
 
Delphi 12 Athens
 
#7

AW: VirtualStringTree in Thread

  Alt 2. Jul 2020, 00:22
Na klar, du verwendest in dem Thread ja auch die globale Variable form2.
Es wird also immer nur in dieser Form der Tree gefüllt.

Übergib dem Thread die gewünscht Form-Instanz und verwende sie in dem Thread.

Tipp: Wenn du die Form2 selbst erstellst, dann schmeiß die automatisch erzeugte Form-Instant ganz weg, am Besten auch gleich diese globale Variable löschen.
Dann siehst'e wie schön es in deinem Thread knallt, wenn nicht mehr auf die globale Variable zugegriffen werden kann.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Zodi
Zodi

Registriert seit: 19. Jul 2017
Ort: Berlin
45 Beiträge
 
Delphi XE7 Ultimate
 
#8

AW: VirtualStringTree in Thread

  Alt 2. Jul 2020, 00:51
Meinst du dem Thread die Form.Handle übergeben?


Na klar, du verwendest in dem Thread ja auch die globale Variable form2.
Es wird also immer nur in dieser Form der Tree gefüllt.

Übergib dem Thread die gewünscht Form-Instanz und verwende sie in dem Thread.

Tipp: Wenn du die Form2 selbst erstellst, dann schmeiß die automatisch erzeugte Form-Instant ganz weg, am Besten auch gleich diese globale Variable löschen.
Dann siehst'e wie schön es in deinem Thread knallt, wenn nicht mehr auf die globale Variable zugegriffen werden kann.
Pascal
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
928 Beiträge
 
#9

AW: VirtualStringTree in Thread

  Alt 2. Jul 2020, 10:19
Wenn du per synchronize eine Methode des MainThreads ausführst, in der du dann die Daten direkt in die VST füllt, läuft diese Methode aber trotzdem im Thread und VST quittiert das mit einer passenden Meldung, dass das aus einem Thread nicht geht.
Du solltest die Daten per Synchronize an eine Datenstruktur im MainThread, auch über synchronize, übergeben, und anschließen schickst per PostMessage eine Msg an den Hauptthread. Nun kann der Hauptthread ein seinem eigenen Kontext das VST befüllen.

Hier mal aus dem Kopf, wie das ablaufen kann:

MainForm:
Delphi-Quellcode:
inferface

const
  WM_UPDATEVST = WM_USER + 1;
.
.
.
private
  LocalData: TDatenStruktur;
  procedure BuildVSTData;
public
  procedure UpdateVSTData(msg: TMessage); message WM_UPDATEVST;
  procedure UpdateDataFromThread(ThreadData: TDatenStruktur);
end;
.
.
.
implementation

procedure TMainForm.BuildVSTData;
begin
  //was auch immer du machst um deine Daten in die VST zu kriegen
end;

procedure TMainForm.UpdateVSTData(msg: TMessage);
begin
  BuildVSTData;
end;

procedure UpdateDataFromThread(ThreadData: TDatenStruktur);
begin
  LocalData.Assign(ThreadData); //Daten übertragen aus dem Thread in die Daten der MainForm
end;
Thread: (Im Create musst du das Handle der MainForm übergeben).
Delphi-Quellcode:
procedure Execute;
var
  FThreaData: TDatenStruktur;
begin
  FThreadData:=TDatenStruktur.Create;
  try
    //Daten sammeln
    synchronize(procdure
      begin
        frmMainForm.UpdateDataFromThread(FThreadData);
      end);
    PostMessage(MainThreadHandle, WM_UPDATEVST, 0, 0);
  finally
    FThreadData.Free;
  end;
end;
Ich habe das hier so einfach reingeklöppelt (bin grad nicht am Rechner). Wird also so nicht AdHoc funktionieren. Aber wie ich das meine wird schon deutlich.
So kannst du das machen. Die Daten übergibst du im Threadcontext, aber das befüllen der VST läuft dann im MainFormContext.

Man muss das natürlich noch einiges verfeinern.
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 Zodi
Zodi

Registriert seit: 19. Jul 2017
Ort: Berlin
45 Beiträge
 
Delphi XE7 Ultimate
 
#10

AW: VirtualStringTree in Thread

  Alt 2. Jul 2020, 20:27
Es geht leider immer noch nicht.

Irgendwie weis das VST oder der Thread nicht in Welche Form er schreiben soll.
Hab hier mal meinen Code in ne .rar angehängt.
Angehängte Dateien
Dateityp: rar VST with Thread.rar (82,8 KB, 3x aufgerufen)
Pascal
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 10:40 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