Einzelnen Beitrag anzeigen

blackdrake

Registriert seit: 21. Aug 2003
Ort: Bammental
618 Beiträge
 
Delphi 10.3 Rio
 
#17

Re: Programm abrupt beenden ohne Memory Leaks

  Alt 15. Sep 2007, 22:12
Hallo.

Habe jetzt endlich wieder Zeit gefunden, mich mit dem Problem zu beschäftigen und konnte es lösen. Außerdem verstehe ich nun die genaue Funktionsweise von Abort(). Der Aufruf von Abort() führt zu der Exception EAbort, die dann durchgeschleift wird und alle Aktionen der Methoden in der Aufrufhierarchie beendet bzw. zu deren except Teil der try..except's führt. In meinem letzten Post war die Progress-Methode nicht innerhalb der Hierarchie und deswegen schlug Abort() fehl (glaube ich).

@negaH: Bei der Entwicklung vermeide ich es in der Regel, zu viele Baustellen auf einmal aufzumachen. Deswegen war in meinem vorherigen Code noch Application.Terminated anstatt WartenForm.FAbort. Bei meinem Programm hat der Verschlüsselungsbutton keine Re-Entranz, da das Form beim Klicken unsichtbar wird und ein Wartenformular mit einem Abbrechenbutton erscheint. Da Start/Stop in sofern auf 2 Buttons aufgeteilt ist, ist FAction unnötig.

Für die, die eventuell das selbe Problem haben, füge ich die Lösung nun an.

KaZIP selbst stellt keine Streams zur Verfügung. Doch nach kurzer Überlegung mit ich auf die Idee gekommen, Abort() in die On(De)Compress/OnAdd-Methoden von KaZIP zu packen:

Delphi-Quellcode:
procedure TMainForm.kazip_add(Sender: TObject; ItemName: string);
begin
  application.processmessages;
  if WartenForm.FAbort then sysutils.Abort;
end;
Um die ZLib Aktionen abzubrechen, habe ich die Progress-Methode in eine eigene Klasse gepackt:

Delphi-Quellcode:
type
  TZLIBProgress = class(TObject) // Ist die Ableitung von TObject eigentlich hierfür sinnvoll?
  public
    procedure Progress(Sender: TObject; tag: Integer; Percent: Integer);
    constructor Create;
    destructor Destroy; override;
  end;

{ ************************ TZLIBProgress ************************ }

procedure TZLIBProgress.Progress(Sender: TObject; tag: Integer; Percent: Integer);
begin
  WartenForm.pbr_progress.Position := Percent * WartenForm.pbr_progress.max div 100;
  Application.ProcessMessages;
  if WartenForm.FAbort then SysUtils.abort;
end;

constructor TZLIBProgress.Create;
begin
  inherited Create;
end;

destructor TZLIBProgress.Destroy;
begin
  inherited Destroy;
end;
Die Anwendung:

Delphi-Quellcode:
function DeCompressFile(InputFileName, OutputFileName: string): boolean;
var
  CompressInputStream: TFileStream;
  CompressOutputStream: TStreamProgressAdapter;
  DeCompressionStream: ZLib.TDeCompressionStream;
  CProgress: TCommonProgress;

  Buf: array[0..4095] of Byte;
  Count: Integer;
begin
  result := true;
  CompressInputStream := TFileStream.Create(InputFileName, fmOpenRead);
  try
    CompressOutputStream := TStreamProgressAdapter.Create(TFileStream.Create(OutputFileName, fmCreate), 0);

    try
      DecompressionStream := TDecompressionStream.Create(CompressInputStream);
      try
        CProgress := TCommonProgress.Create;
        try
          try
            CompressOutputStream.OnProgress := CProgress.Progress;
            while true do
            begin
              Count := DeCompressionStream.Read(Buf[0], SizeOf(Buf));
              if Count = 0 then
                break
              else
                CompressOutputStream.Write(Buf[0], Count);
            end;
          except
            on E: Exception do
            begin
              result := false;
              if not (E is EAbort) then raise;
            end;
          end;
        finally
          CProgress.Free;
        end;
      finally
        DecompressionStream.Free;
      end;
    finally
      CompressOutputStream.Free;
    end;
  finally
    CompressInputStream.Free;
  end;
end;

function CompressFile(InputFileName, OutputFileName: string): boolean;
var
  CompressInputStream: TStreamProgressAdapter;
  CompressOutputStream: TFileStream;
  CompressionStream: ZLib.TCompressionStream;
  CProgress: TCommonProgress;
begin
  result := true;
  CompressInputStream := TStreamProgressAdapter.Create(TFileStream.Create(InputFileName, fmOpenRead), 0);
  try
    CompressOutputStream := TFileStream.Create(OutputFileName, fmCreate);
    try
      CompressionStream := TCompressionStream.Create(clMax, CompressOutputStream);
      try
        CProgress := TCommonProgress.Create;
        try
          try
            CompressInputStream.OnProgress := CProgress.Progress;
            CompressionStream.CopyFrom(CompressInputStream, CompressInputStream.Size);
          except
            on E: Exception do
            begin
              result := false;
              if not (E is EAbort) then raise;
            end;
          end;
        finally
          CProgress.Free;
        end;
      finally
        CompressionStream.Free;
      end;
    finally
      CompressOutputStream.Free;
    end;
  finally
    CompressInputStream.Free;
  end;
end;
Danke für euere Ratschläge!

Gruß
blackdrake

[edit=SirThornberry]Code-Highlighting korrigiert - Mfg, SirThornberry[/edit]
Daniel Marschall
  Mit Zitat antworten Zitat