Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#21

AW: CopyFile lässt die Anwendung hängen, wie umgehen?

  Alt 4. Jun 2015, 19:52
@mm1256

Also deine FileCopy-Routine ist echt grausam ... wer hat die denn verbrochen?

Ich wollte die gerade etwas überarbeiten, aber das kommt ja einem neu schreiben gleich.
  1. Statt einem String als Rückgabe verwende Exceptions
  2. Solche Exceptions raise Exception.Create('Da hat der Programmierer was vergessen'); sind nicht gerade aussagekräftig. Mach es doch richtig:
    Delphi-Quellcode:
    case FileCopyMode of
      ...
      else raise ENotImplemented.CreateFmt('FileCopyMode %s nicht implementiert', [GetEnumName( TypeInfo(TFileCopyMode), Ord( FileCopyMode )]);
    end;
    und du bekommst die Fehlermeldung
    Zitat:
    FileCopyMode fcmFoo nicht implementiert
  3. Statt Delphi-Referenz durchsuchenTStream.ReadBuffer solltest du Delphi-Referenz durchsuchenTStream.Read verwenden, dann bekommst du automatisch die Anzahl der echten gelesenen Bytes zurück. Dann weißt du auch wieviel du schreiben musst
  4. Statt einer TFileCopyCallback = procedure(ProgressPercent: Integer) of object; nimm eine TFileCopyCallback = reference to procedure(ProgressPercent: Integer); (optional, weil flexibler)
Wenn du das hast, dann kannst du diese Kopieraktion vom http://www.delphipraxis.net/185335-b...ab-xe2%5D.html aus starten und alles wird gut.
Delphi-Quellcode:
procedure TFoo.FileCopyWorker_DoWork(Sender: TObject; e: TDoWorkEventArgs );
var
  FileCopyArg : TFileCopyArg;
begin
  FileCopyArg := e.Argument.AsType<TFileCopyArg>;
  MyCopyFile(
    FileCopyArg.SourceName,
    FileCopyArg.DestName,
    FileCopyArg.FileCopyMode,
    (Sender as TBackgroundWorker).ReportProgress );
end;

procedure TFoo.FileCopyWorker_ProgressChanged( Sender : TObject; e: TProgressChangedEventArgs );
begin
  ProgressBar1.Position := e.Value;
end;

procedure TFoo.FileCopyWorker_RunWorkerCompleted( Sender: TObject; e: TRunWorkerCompletedEventArgs );
begin
  if Assigned( e.Error ) then
    ShowMessage( e.Error.ToString() )
  else if e.Cancelled then
    ShowMessage( 'Du hast das abgebrochen!' )
  else
    ShowMessage( 'Ich habe fertig!' );
end;
Das ist eigentlich alles und du kannst die originale Routine verwenden.

PS Das Wichtigste hatte ich vergessen:
Du greifst immer wieder auf SourceStream.Size zu, und das macht deine Routine mit Progress-Callback extremst langsam. Denn bei jedem Aufruf wandert der Stream an das Ende liest die Position und kehrt zur vorherigen Position zurück!

Lies den Wert am Anfang einmal aus und merk dir diesen, dann läuft auch die Routine mit dem Progress sehr schnell.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 4. Jun 2015 um 20:08 Uhr)
  Mit Zitat antworten Zitat