Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Schwierigkeiten mit 7-zip und Events (https://www.delphipraxis.net/191074-schwierigkeiten-mit-7-zip-und-events.html)

a.def 5. Dez 2016 14:31

Schwierigkeiten mit 7-zip und Events
 
Ich habe vor Kurzem die SevenZIPVCL-Komponente (http://www.yard2usb.de/joomla/index....i-tsevenzipvcl) entdeckt und auch gleich ein Mini-Demo geschrieben.

Ich benutze die Version 0.7.6 und so sieht mein Button der Demo aus
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
 aSevenZip: TSevenZip;
begin
 Caption := 'Compressing ...';

 aSevenZip := TSevenZip.Create(Self);

 try
  // aSevenZip.OnProgress := SevenZipOnProgress;
  // aSevenZip.OnAddfile := SevenZipOnAddFile;

  aSevenZip.AddRootDir := 'E:\7ztest\';
  aSevenZip.SZFileName := ExtractFilePath(Application.ExeName) + 'Test.7z';
  // aSevenZip.Password := '123456';

  aSevenZip.LZMACompressType := LZMA; // LZMA, PPMD
  aSevenZip.LZMACompressStrength := NORMAL; // SAVE, FAST, NORMAL, MAXIMUM, ULTRA
  aSevenZip.AddOptions := []; // AddRecurseDirs, AddSolid, AddStoreOnlyFilename, AddIncludeDriveLetter, AddEncryptFilename

  aSevenZip.Files.Clear;
  aSevenZip.Files.AddString('E:\7ztest\249MB.123');
  aSevenZip.Files.AddString('E:\7ztest\123\456.txt');
  aSevenZip.Files.AddString('E:\7ztest\456');

  // aSevenZip.SevenZipComment := 'Comment!';

  aSevenZip.add;
 finally
  aSevenZip.Free;
 end;

 Caption := 'Done';
end;
Das funktioniert einwandfrei.
Nur sobald ich OnProgress, OnAddfile oder beides verwende, scheint mein Demo-Programm (welches nur diesen Button und eine ProgressBar hat) zu hängen.

Die Event-Prozeduren sehen so aus
Delphi-Quellcode:
procedure TForm1.SevenZipOnProgress(Sender: TObject; Filename: WideString; FilePosArc, FilePosFile: Int64);
begin
 ProgressBar1.Position := FilePosArc;
 Application.ProcessMessages;
end;

procedure TForm1.SevenZipOnAddFile(Sender: TObject; Filename: WideString; Filesize: Int64);
begin
 Caption := Filename;
 ProgressBar1.Position := 0;
 ProgressBar1.Max := Filesize;
end;
Ist das ein Bug? Denn egal was in den Event-Prozeduren steht, es führt immer zum Stillstand der Demo.
Es scheint so, als ob die Demo nur hängt, wenn in den Events irgendwas steht was mit der VCL zu tun hat. Wenn ich dort reinschreibe i:=123; hängt sich nichts auf.

mensch72 5. Dez 2016 14:48

AW: Schwierigkeiten mit 7-zip und Events
 
..."Es scheint so, als ob die Demo nur hängt, wenn in den Events irgendwas steht was mit der VCL zu tun hat."...

Wenn man die Callbackquelle innerhalb von 7Zip nicht kennt, gehe man davon aus, das es dort in/durch einen Thread aufgerufen wird.

-> Also hier NIX mit VCL und KEIN Application.ProcessMessages... besser im Event nur irgendetwas einfaches ala PostMessage, Syncronize, CallInMainTread oä.

a.def 5. Dez 2016 15:15

AW: Schwierigkeiten mit 7-zip und Events
 
Zitat:

Zitat von mensch72 (Beitrag 1355391)
..."Es scheint so, als ob die Demo nur hängt, wenn in den Events irgendwas steht was mit der VCL zu tun hat."...

Wenn man die Callbackquelle innerhalb von 7Zip nicht kennt, gehe man davon aus, das es dort in/durch einen Thread aufgerufen wird.

-> Also hier NIX mit VCL und KEIN Application.ProcessMessages... besser im Event nur irgendetwas einfaches ala PostMessage, Syncronize, CallInMainTread oä.

Ich habe das gerade auch mal flott mit TJcl7zCompressArchive getestet. Dort genau dasselbe Problem.

Wie würde das denn im Mainthread mit Postmessage funktionieren?
Ich benutze der Einfachheit halber jetzt die JEDI-Komponenten. Es wird aber dieselbe DLL verwendet.

Folgendes scheint scheinbar nicht zu funktionieren (GUI wird nicht aktualisiert)
Delphi-Quellcode:
const
 WM_UPDATE_PB = WM_USER;

procedure UpdateMessage(Value: Int64);
begin
 PostMessage(Form1.Handle, WM_UPDATE_PB, Value, 0);
end;

procedure TForm1.WMUpdatePB(var msg: TMessage);
begin
 ProgressBar1.Position := msg.WParam;
 Application.ProcessMessages;
end;

procedure TForm1.JclOnProgress(Sender: TObject; const Value, MaxValue: Int64);
begin
 UpdateMessage(Value);
 // ProgressBar1.Position := Value;
 // Application.ProcessMessages;
end;

mensch72 5. Dez 2016 16:20

AW: Schwierigkeiten mit 7-zip und Events
 
http://docwiki.embarcadero.com/RADSt...andling_Method

es fehlt dir wohl noch der "MessageMap" im Form
Delphi-Quellcode:
protected
   procedure UserMsgProc(var Message: TMessage); message WM_USER;
end;
(und ich würde statt "Application.ProcessMessages;" lieber "ProgressBar1 .Update .Repaint .Invalidate" verwenden wenn es das gibt. Wenn etwas nur mit "ProcessMessages" geht, ist meist das Konzept nicht so wirklich gut)

hoika 5. Dez 2016 16:24

AW: Schwierigkeiten mit 7-zip und Events
 
Hallo,
wenn intern ein Thread benutzt wird, fehlt vielleicht nur Synchronize beim Upate der GUI im Hauptprogramm.

a.def 5. Dez 2016 17:23

AW: Schwierigkeiten mit 7-zip und Events
 
Zitat:

Zitat von mensch72 (Beitrag 1355411)
http://docwiki.embarcadero.com/RADSt...andling_Method

es fehlt dir wohl noch der "MessageMap" im Form
Delphi-Quellcode:
protected
   procedure UserMsgProc(var Message: TMessage); message WM_USER;
end;
(und ich würde statt "Application.ProcessMessages;" lieber "ProgressBar1 .Update .Repaint .Invalidate" verwenden wenn es das gibt. Wenn etwas nur mit "ProcessMessages" geht, ist meist das Konzept nicht so wirklich gut)

In der offiziellen JEDI-Demo ist er auch nicht vorhanden und dort funktioniert das Aktualisieren der GUI auch nicht.

Zitat:

Zitat von hoika (Beitrag 1355412)
Hallo,
wenn intern ein Thread benutzt wird, fehlt vielleicht nur Synchronize beim Upate der GUI im Hauptprogramm.

Mein Code wird im Hauptthread ausgeführt.

Ich habe mal ein bisschen rumgespielt und den Code im Button in Folgendes gepackt
Delphi-Quellcode:
TThread.CreateAnonymousThread(
 procedure
  begin
  end).Start:
Dann funktioniert es. Aber warum nicht schon mit PostMessage usw.? Damit habe ich es ja auch versucht.

Ghostwalker 5. Dez 2016 17:34

AW: Schwierigkeiten mit 7-zip und Events
 
Jaja.....nur die DLL, die nutzt sehr wohl Threads.

mensch72 5. Dez 2016 18:13

AW: Schwierigkeiten mit 7-zip und Events
 
wenn du magst, hänge das gezippte Projekt deines "MiniTestProg" mal hier an eine Antwort an. Wenn ich am WE dazu komme kann ich mal schaun was mein PC dazu sagt;)

Bei deinem "TThread.CreateAnonymousThread" ist es mir nicht ganz wohl, du entkoppelst dich zwar von dem externen DLL Thread, aber echt sauber im MainThread der VCL bist du so auch noch nicht.

Das PostMessage mit einer "selbst gemappten" MessageProc oder einer Komponente ala "AppMessage" wo man sich seine Message im Event raussucht wäre mir hier für alles was ich sonst noch in der GUI vor hätte die sicherste und einfachste Lösung. Man kann das sicher auch mit eigenen (Async)Threads oder Synchronize hinbekommen, aber als fauler Mensch fehlt mir dazu der Elan.

a.def 5. Dez 2016 18:57

AW: Schwierigkeiten mit 7-zip und Events
 
Ich poste hier mal meine erste halbwegs funktionierende Lösung.
Aktuell funktioniert ZIP und 7z. GZip warum auch immer noch nicht.

Delphi-Quellcode:
const
 WM_SYNC_ARCHIVE_PROGRESS = WM_USER + 153;

procedure TForm1.WMSyncArchiveProgress(var Message: TMessage);
begin
 ProgressBar1.Max := Message.LParam;
 ProgressBar1.Position := Message.WParam;
end;

procedure TForm1.JclCompressionArchiveProgress(Sender: TObject; const Value, MaxValue: Int64);
var
 MyValue, MyMaxValue: Int64;
begin
 MyValue := Value;
 MyMaxValue := MaxValue;

 while MyMaxValue > High(Byte) do
  begin
   MyMaxValue := MyMaxValue shr 8;
   MyValue := MyValue shr 8;
  end;

 PostMessage(Handle, WM_SYNC_ARCHIVE_PROGRESS, MyValue, MyMaxValue);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 aFile: string;
 aCompressArchive: TJclCompressionArchive;
 aCompressFormat: TJclCompressArchiveClass;
begin
 TThread.CreateAnonymousThread(
   procedure
  begin
   aFile := ExtractFilePath(Application.ExeName) + Edit1.Text; // Edit1 z.B. "Test.7z" oder "Test.zip"
   aCompressFormat := GetArchiveFormats.FindUpdateFormat(aFile);

   if aCompressFormat <> nil then
    begin
     Caption := 'Compressing ...';

     aCompressArchive := aCompressFormat.Create(aFile);

     try
      aCompressArchive.OnProgress := JclCompressionArchiveProgress;
      aCompressArchive.Password := '123456';

      (aCompressArchive as TJclCompressArchive).AddFile('249MB.123', 'E:\7ztest\249MB.123');
      (aCompressArchive as TJclCompressArchive).AddFile('456.txt', 'E:\7ztest\123\456.txt');
      (aCompressArchive as TJclCompressArchive).AddFile('456', 'E:\7ztest\456');

      if (aCompressArchive.ClassType = JCLCompression.TJcl7zCompressArchive) or (aCompressArchive.ClassType = JCLCompression.TJcl7zUpdateArchive) then
       begin
        ShowMessage('7z');

        // - SetEncryptionMethod for 7z not available
        (aCompressArchive as TJcl7zUpdateArchive).SetCompressionLevel(6); // 0 .. 9
        (aCompressArchive as TJcl7zUpdateArchive).SetCompressHeader(True);

        if aCompressArchive.Password <> '' then
         (aCompressArchive as TJcl7zUpdateArchive).SetEncryptHeader(True);
       end
      else if (aCompressArchive.ClassType = JCLCompression.TJclZIPCompressArchive) or (aCompressArchive.ClassType = JCLCompression.TJclZipUpdateArchive) then
       begin
        ShowMessage('zip');

        // - SetEncryptHeader/SetCompressHeader for zip not available
        (aCompressArchive as TJclZipUpdateArchive).SetNumberOfPasses(3);
        (aCompressArchive as TJclZipUpdateArchive).SetCompressionLevel(7); // 0 .. 9
        (aCompressArchive as TJclZipUpdateArchive).SetCompressionMethod(TJclCompressionMethod.cmDeflate);

        if aCompressArchive.Password <> '' then
         (aCompressArchive as TJclZipUpdateArchive).SetEncryptionMethod(emAES256); // emNone, emAES128, emAES192, emAES256, emZipCrypto
       end
      else if (aCompressArchive.ClassType = JCLCompression.TJclGZipCompressArchive) or (aCompressArchive.ClassType = JCLCompression.TJclGZipUpdateArchive) then
       begin
        ShowMessage('Gzip');

        (aCompressArchive as TJclGZipUpdateArchive).SetCompressionLevel(7); // 0 .. 9
        (aCompressArchive as TJclGZipUpdateArchive).SetNumberOfPasses(3);
       end
      else
       FreeAndNil(aCompressArchive);

      if aCompressArchive <> nil then
       (aCompressArchive as TJclCompressArchive).Compress; // Funktioniert bei Gzip noch nicht
     finally
      FreeAndNil(aCompressArchive);

      Caption := 'Done';
     end;
    end;
  end).Start;
end;
Zitat:

Bei deinem "TThread.CreateAnonymousThread" ist es mir nicht ganz wohl, du entkoppelst dich zwar von dem externen DLL Thread, aber echt sauber im MainThread der VCL bist du so auch noch nicht.
Das ist nur zu Testzwecken. Aber letztlich läuft es eh darauf hinaus, dass das alles in einem TThread landet.

mensch72 6. Dez 2016 09:25

AW: Schwierigkeiten mit 7-zip und Events
 
"Caption := " und "ShowMessage" wieder/noch einfach so in einem (Anonymous)Thread... auch wenn nur zum schnellen Test... das geht so nicht auf Dauer gut


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:17 Uhr.
Seite 1 von 2  1 2      

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