Einzelnen Beitrag anzeigen

mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#18

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

  Alt 4. Jun 2015, 14:26
Zitat von AlexII:
Ich habe einfach noch nie mit Threads gearbeitet... aber muss wohl jetzt.
Mir geht es ähnlich. Wenn es vermeidbar ist mit Threads zu arbeiten, dann tue ich es. Aber wahrscheinlich ist es wie Radfahren lernen.

Ich hab eine Routine zum Files kopieren, die würde ich auch gerne ab und zu mal in einen Thread packen. Das Problem - aus meiner Sicht - ist die Synchronisation des ProgressBar im Formular. So sieht es momentan aus:

Delphi-Quellcode:
...
type
  TFileCopyMode = (fomAlways, fomIfNewer, fomIfOlder, fomIfSameDate, fomIfSameDateTime);
  TFileCopyCallback = procedure(ProgressValue: Integer) of object;

...

function MyCopyFile(SourceName, DestName: string;
                    FileCopyMode: TFileCopyMode;
                    Progress: TFileCopyCallback): string;
var
  BytesRead, BytesToRead, P, Percent: Int64;
  SourceStream, DestStream: TFileStream;
  SourceDateTime, DestDateTime: TDateTime;
begin
  Result := '';
  if not FileExists(SourceName) then Exit('Quelldatei <'+SourceName+'> existiert nicht');
  if not FileAge(SourceName, SourceDateTime) then Exit('Quelldatei: TimeStamp lesen fehlgeschlagen');
  BytesRead := 0;
  Percent := 0;
  P := 0;
  // DestName darf auch ein Directory sein...dann den Dateinamen ran hängen
  if DirectoryExists(DestName) // DestName ist ein Directory
  then DestName := IncludeTrailingBackslash(DestName)+ExtractFileName(SourceName);
  if FileExists(DestName) then begin
    if not FileAge(DestName, DestDateTime) then Exit('Zieldatei: TimeStamp lesen fehlgeschlagen');
    case FileCopyMode of
      fomAlways :;// immer kopieren
      fomIfNewer : // Die Quelldatei muss neuer als die Zieldatei sein
                          if NOT (SourceDateTime > DestDateTime)
                          then Exit('Die Quelldatei ist nicht neuer als die Zieldatei');
      fomIfOlder : // Die Quelldatei muss älter als die Zieldatei sein => z.B. Downgrade
                          if NOT (SourceDateTime < DestDateTime)
                          then Exit('Die Quelldatei ist nicht älter als die Zieldatei');
      fomIfSameDate : // Quell- und Ziel-Datei müssen am selben Tag erstellt worden sein
                          if Trunc(DestDateTime) <> Trunc(SourceDateTime)
                          then Exit('Die Zieldatei ist nicht vom selben Datum als die Quelldatei');
      fomIfSameDateTime : // Das Datum von Quell- und Ziel-Datei muss identisch sein
                          if DestDateTime <> SourceDateTime
                          then Exit('Datum und Zeit von Zieldatei und Quelldatei sind unterschiedlich');
      else raise Exception.Create('Da hat der Programmierer was vergessen');
    end;
  end;
  SourceStream := TFileStream.Create(SourceName,fmOpenRead or fmShareDenyNone);
  DestStream := TFileStream.Create(DestName,fmCreate);
  try
    if @Progress = nil
    then DestStream.CopyFrom(SourceStream,SourceStream.Size) // so geht es am schnellsten
    else begin // mit Fortschrittanzeige
      Progress(0);
      BytesToRead := SizeOf(StreamCopyBuffer);
      if SourceStream.Size < BytesToRead then BytesToRead := SourceStream.Size;
      repeat
        SourceStream.ReadBuffer(StreamCopyBuffer,BytesToRead);
        DestStream.WriteBuffer(StreamCopyBuffer,BytesToRead);
        BytesRead := BytesRead + BytesToRead;
        Percent := (BytesRead * 100) div SourceStream.Size;
        if P <> Percent then begin
          Progress(Integer(Percent));
          P := Percent;
        end;
        if (SourceStream.Size - BytesRead) <= BytesToRead
        then BytesToRead := SourceStream.Size - BytesRead;
      until BytesRead >= SourceStream.Size;
      if BytesRead <> SourceStream.SIZE
      then Result := 'Fehler beim Kopiervorgang:'+#13#10
                     +'Bytes gelesen:' + IntToStr(BytesRead) + #13#10
                     +'Bytes geschrieben:' + IntToStr(SourceStream.SIZE)
      else Progress(100);
    end;
  finally
    SourceStream.Free;
    DestStream.Free;
  end;
  if Result = ''
  then MySetAllFileDates(DestName, SourceDateTime, SourceDateTime, SourceDateTime);
end;
Womit dem TE ja auch geholfen wäre ist die Frage: Wie packt man das in einen Thread?
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat