![]() |
VirtualStringTree in Thread
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:
Wenn ich aber im ButtonClick nicht den Tread starte sondern die VST direkt fülle.....
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.
Delphi-Quellcode:
dann geht es was mache ich falsch?
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; |
AW: VirtualStringTree in Thread
Du muss die Daten an den MainThread schicken und das Befüllen des VirtualStringTree auch im MainThread machen.
|
AW: VirtualStringTree in Thread
Du hast eine Methodenaufruf
Delphi-Quellcode:
im Code. Darin passiert aber gar nichts. Alles, was du mit dem VST machst, muss im Main Thread ausgeführt werden. Sprich, in die
Synchronize(DoSomething)
Delphi-Quellcode:
Methode rein.
DoSomething()
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. |
AW: VirtualStringTree in Thread
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. |
AW: VirtualStringTree in Thread
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:
Jedenfals wird so die VST nicht befüllt.
procedure TForm1.BitBtn1Click(Sender: TObject);
var TestForm: TForm2; begin TestForm := TForm2.Create(nil); TestForm.Show; end; Wenn ich es allerding so mache dann geht es wobei dann nur 1 Formural angezeit wird.
Delphi-Quellcode:
Wo bin ich das auf dem Holzweg?
procedure TForm1.BitBtn1Click(Sender: TObject);
begin TestForm.Show; end; |
AW: VirtualStringTree in Thread
Das sind etwas wenige Informationen zum Befüllen des VST. Wenn du damit Probleme hast, dann solltest du den SourceCode sinnvollerweise auch hier zeigen. :stupid:
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 :glaskugel: 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. |
AW: VirtualStringTree in Thread
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. |
AW: VirtualStringTree in Thread
Meinst du dem Thread die Form.Handle übergeben?
Zitat:
|
AW: VirtualStringTree in Thread
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:
Thread: (Im Create musst du das Handle der MainForm übergeben).
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;
Delphi-Quellcode:
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.
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; 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. |
AW: VirtualStringTree in Thread
Liste der Anhänge anzeigen (Anzahl: 1)
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:56 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 by Thomas Breitkreuz