In einem Trehad ein Dialog auf rufen und wieder schließen ?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben:Natürlich ist für diese Aufgabe Thread Praktisch. Da ich noch andres sachen machen möchte. Wie oft den noch ?
z.b. möchte ich ein Archiv Öffnen und gleichzeitig Verzeichnisse Kopieren können.
Wie könnte man das ohne Thread denn Lösen ?
Was heisst gleichzeitig? Wie lange dauert's denn ein Archiv zu öffnen? Ne halbe Stunde?

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ich weiß nicht theo.... ohne Thread ist das ganze aber nicht so schön.
Für mein Ziel. ich hoffe dir ist mein Ziel inzwischen klar geworden.
Was ich vorhabe.

ich habe eine Oberfläche mit X Fenster(Panels) Drauf, die der User zu Laufzeit erstellen kann. Diese Panels haben verschiedene, Funktionen:
1: Ein Datei Browser
du kannst Dateien und Verzeichnisse löschen, Verschieben, Kopieren, Komprimieren, Archive Öffnen.
Du kannst aber auch Dateien Anschauen oder aber Verzeichnisse anlegen.
und ich möchte gerne das der User während er ein Archiv Komprimiert, Verzeichnisse z.b. Verschieben oder Löschen oder beides kann.

und meines Wissen geht das nur mit Threads oder etwa nicht ?
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

du bist aber schnell heute mit antworten *G*.

naja kommt auf die Archiv Größe an z.b. Montas Archiv zu Öffnen dauert schon ca ne halbe Minuten würde ich sagen. Aber größer Archive Dauern einfach länger.

ich setzte jetzt einfach schnullerbacke Vorschlag um, weil ich glaube ich haben ihn jetzt verstanden wie er es gemeint hat.
MFG
Michael Springwald

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

kann ich das Ereigniss denn auch im Thread also bei
Execute aufrufen ?
weil ich habe nur einen zustand. es sei denn ich nehme noch Speedbutton.enabled dazu.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben: naja kommt auf die Archiv Größe an z.b. Montas Archiv zu Öffnen dauert schon ca ne halbe Minuten würde ich sagen. Aber größer Archive Dauern einfach länger.
So lange? Na gut, dann kann es sich lohnen.

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@pluto

Bau dir eine StruKtur:

Code: Alles auswählen

type
 
  TParamStruct = class(TObject)
    // hier können Felder oder auch ganze Objekte drin stehen
  end;
 
  TMyThread = class(TTread)
  private
    FParams: TParamStruct;
  published
    property Params: TParamStruct read FParams write FParams;
  end;
Auf die Art kannst du die innerhalb des Threads ändern und von außerhalb abrufen und ebenfalls ändern. Das könnte dann auch durchaus ein Dialog sein, da sind deiner Phantasie keine Grenzen gesetzt. Sogar SyncMode könnte so von außen geändert werden. Das darf aber nur während Synchronize stattfinden sonst geht das grausam in die Hosen.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ich habe das jetzt so bis her:

Code: Alles auswählen

TSynModusSet = (SPEnabledTrue,SPEnabledFalse,LWAddItems);
  TSynmodus = SPEnabledTrue..LWAddItems;
 
  TSynEvt = procedure(Typ:TSynmodus) of object;      
bei TForm1:
.....
  public
    Treahd:TBackupThread;
    procedure SynEvt(Typ:TSynmodus);
 
 
procedure TForm1.SynEvt(Typ:TSynmodus);
begin
  case typ of
    SPEnabledTrue: begin
    end;
 
    SPEnabledFalse: begin
    end;
 
    LWAddItems: begin
    end;
  end;
end;
Dort wollte ich dann die entsprechende Funktionen auf rufen. Ich Dachte auch an Pointer würde das auch gehen ?
da ich ja nur ein Pointer auf eine TListItem klasse brauche.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

SynEvt muss Parameterlos sein, damit du sie mit Synchronize aufrufen kannst weil: TThreadMethod = procedure of object;
Du kannst den Modus als Feld der TThread Ableitung definieren.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ich habe es jetzt so:

Code: Alles auswählen

TSynModusSet = (SPEnabledTrue,SPEnabledFalse,LWAddItems,lwAddItems2,lwpunkt);
  TSynmodus = SPEnabledTrue..lwpunkt;
 
  TSynEvt = TThreadMethod;
 
  TBackupThread = class(TThread)
  private
    Status: string;
    fSynModus:TSynmodus;
    items:TStringlist;
    procedure scd;
 
 
    procedure StopTimer;
    procedure Progress;
  protected
    procedure Execute; override;
 
  public
    onSynEv:TSynEvt;
    Cancel:Boolean;
    tag:Integer;
    files:TStringlist;
    Para:String;
    lw:TListView;
    Constructor Create(CreateSuspended : boolean);
    destructor Destroy;
 
  end; 
 
constructor TBackupThread.Create(CreateSuspended : boolean);
begin
  items:=TStringlist.Create;
  tag:=0;
  FreeOnTerminate := True;
  Cancel:=False;
  inherited Create(CreateSuspended);
end;
 
destructor TBackupThread.Destroy;
begin
 
end;
 
procedure TBackupThread.scd;
begin
  Synchronize(onSynEv);
end;
 
procedure TBackupThread.StopTimer;
begin
  Form1.SpeedButton14.Enabled:=True;
end;
 
procedure TBackupThread.Progress;
begin
  Form1.SpeedButton14.Enabled:=False;
end;
 
procedure TBackupThread.Execute;
const
  READ_BYTES = 1;//2048;
var
  M: TMemoryStream;
  P: TProcess;
  n: LongInt;
  BytesRead: LongInt;
  str,fz:String;
  t:Boolean;
  dir:TDir;
  //lt:TListItem;
begin
//  post
  M := TMemoryStream.Create; BytesRead := 0;
  P := TProcess.Create(nil);
  P.CommandLine := '7za '+Para; P.Options := [poUsePipes];
  P.Execute; t:=False;
  str:=''; SetLength(fz,3);
  fSynModus:=SPEnabledTrue; scd;
 
  Synchronize(@lw.BeginUpdate);
  if (dirlevel > 1) then begin
    fSynModus:=lwpunkt; Synchronize(@scd);
  end;
 
  while (P.Running) and (Cancel = False) do begin
    M.SetSize(BytesRead + READ_BYTES);
    n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES);m.Read(fz[1],1);
    if fz[1] <> #10 then str:=str+fz[1] else begin
      if Pos('Path',str) > 0 then t:=True;
 
      if str = '' then begin
        t:=False; fSynModus:=LWAddItems; Synchronize(@scd);
        items.Clear
      end;
 
      if t = True then
        items.add(str);
      str:='';
    end;
    if n > 0 then Inc(BytesRead, n) else Break;
 //   if BytesRead >=9000 then break;
  end;
 
  Synchronize(@lw.EndUpdate); Synchronize(@lw.BeginUpdate);
  if m.size = 0 then begin
  repeat
    M.SetSize(BytesRead + READ_BYTES);
    n := P.Output.Read((M.Memory + BytesRead)^, READ_BYTES); m.Read(fz[1],1);
    if fz[1] <> #10 then str:=str+fz[1] else begin
      if Pos('Path',str) > 0 then t:=True;
      if str = '' then begin
//        lt:=TListItem.Create(nil);
//        dir:=TDir.Create;dir.dir:=str;dir.TempName:='';
        //lt.Data:=@dir;
        t:=False;
        fSynModus:=LWAddItems; Synchronize(@scd);
        items.Clear
      end;
      if t = True then items.add(str);
      str:='';
    end; if n > 0 then Inc(BytesRead, n) else Break;
  until (n <= 0) and (Cancel = False);
  end;
  Synchronize(@lw.EndUpdate);
 
  M.SetSize(BytesRead);
  p.Free;
  m.Free;
  fSynModus:=SPEnabledFalse;
  Synchronize(@scd);
end;
 
// gehört zu keiner Klasse
procedure AddLV(lv:TListView;s:TStringlist;levelDir:Integer);
var
  str,str2:String;
  dir:TDir;
begin
 
  if (s <> NIL) and (s.count > 0) then begin
    dir:=TDir.Create; dir.TempName:='';
    str2:=TrimLeft(GetToken(s.strings[0],'=',2));
    if pos('D',GetValue(s,'Attributes',3)) = 0 then begin
 
      if Pos('/',str2) > 0 then begin
        if dirlevel <> NumToken(str2,'/') then begin
          str:='['+GetToken(str2,'/',levelDir)+']';
        end
        else
          str:=GetToken(str2,'/',levelDir)
      end
      else begin
        str:=str2;
        writeln(str);
      end;
 
      if GetLVIndex(str,lv) = -1 then begin
        with lv.Items.add do begin
          Caption:=str;
          dir.dir:='"'+str2+'"';
          Data:=dir;
        end;
      end;
    end;
  end
  else begin
    if (s = NIL) then begin
      with lv.Items.add do begin
        Caption:='[..]';
        dir.dir:='[..]';
        Data:=dir;
      end;
    end;
  end;
end;       
 
// Die Auswertung
procedure TForm1.SynEvt;
begin
  case Treahd.fSynModus of
    SPEnabledTrue: begin
      SpeedButton14.Enabled:=True;
    end;
 
    SPEnabledFalse: begin
      SpeedButton14.Enabled:=False;
    end;
 
    LWAddItems: begin
      AddLV(Treahd.lw,Treahd.items,dirLevel);
    end;
 
    lwpunkt: begin
      AddLV(Treahd.lw,nil,dirLevel);
    end;
 
  end;
end;
was haltet ihr davon ?
Es geht auf jeden Fall.

schön theo das ich dich überzeugt habe, das hier Thread sin machen *G*
MFG
Michael Springwald

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@theo

@pluto kann ja aus SynEvt auch einen Event machen:

property OnSyncEvent: TSynEvt read FSynEvt write FSynEvt;

und die Prozedur :

procedure TMyThread.Synchronized;

einrichten. Dann Sonchronize(@Synchronized); und dort dann:

if Assigned(FSynEvt) then OnSyncEvent(FSynModus)
else begin
// interne Verarbeitung
end;

Auf diese Weise darf man auch Schnittstellen mit mehreren Parametern bauen und sogar mit (var ABlubb: TBlubb) Werte in den Thread zurückholen.

@pluto

Mauer dich nicht immer ein, der oben gezeigte kleine Umweg erweitert die Möglichkeiten drastisch.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

ich Dachte Sonchronize(@Synchronized);
das geht nicht wegen den Parameter ?
aber TSynEvt muss doch immer noch Parameter los sein oder ?
MFG
Michael Springwald

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Synchronized hat keine Parameter, dagegen dürfen die Events aber welche haben und da die erst in Synchronized aufgerufen werden ist alles "wunnebar". So könntest du z.B. deine Directory-Liste abgleichen indem du einfach den String nach außen lieferst.

OnUpdateDirList(ADir: string);

Da ist nun etwas Flexibilität im Kopfe gefragt. In Synchronized darfst du eben alles machen was ansonsten nicht geht.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

du meinst also ich könnte alle Variablen nach außen als Private defnieren und anschließen einem Ereignis zuweisen ?

Ich finde so wie das jetzt ist, es ist nicht schlecht.
ich hätte nur noch 3 Fragen:
1: Warum wird der Stop Speedbutton nicht mehr auf Enabled = True gesetzt ?
2: Wie kann ich eine % anzeige für die Prossebar anzeigen.
ich habe gesehen das es dafür eine Eigenschaft gibt:
TextBar oder so ählinch aber es wird kein text angezeigt.
3: Was heißt die VCL ist nicht "Thread Sicher" ?
MFG
Michael Springwald

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

pluto hat geschrieben: 3: Was heißt die VCL ist nicht "Thread Sicher" ?
Wahrscheinlich, dass man besser nicht in Verbindung mit Threads benutzt...

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@Euklid

Hoffentlich nicht, das würde bedeuten, das die Synchronisierung mit dem Mainthread nicht klappt. Damit würden Threads erheblich in ihren Einsatzmöglichkeiten eingeschränkt.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Antworten