Delphi多スレッドによるファイルコピーの仕組み

Delphiでは、TThreadクラスを使用してマルチスレッドでのファイルコピーを実現できます。以下にサンプルコードを示します。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TCopyThread = class(TThread)
  private
    FSourceFile: string;
    FDestFile: string;
  protected
    procedure Execute; override;
  public
    constructor Create(const SourceFile, DestFile: string);
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    FCopyThread: TCopyThread;
    procedure CopyProgress(const BytesCopied, TotalBytes: Int64);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TCopyThread.Create(const SourceFile, DestFile: string);
begin
  inherited Create(True);
  FSourceFile := SourceFile;
  FDestFile := DestFile;
end;

procedure TCopyThread.Execute;
var
  SourceStream, DestStream: TFileStream;
  Buffer: array[0..8191] of Byte;
  BytesRead, BytesWritten: Integer;
begin
  SourceStream := TFileStream.Create(FSourceFile, fmOpenRead or fmShareDenyWrite);
  try
    DestStream := TFileStream.Create(FDestFile, fmCreate);
    try
      repeat
        BytesRead := SourceStream.Read(Buffer, SizeOf(Buffer));
        if BytesRead > 0 then
        begin
          BytesWritten := DestStream.Write(Buffer, BytesRead);
          if BytesWritten <> BytesRead then
            Break;
          Synchronize(procedure
          begin
            // 更新进度显示
            Form1.CopyProgress(SourceStream.Position, SourceStream.Size);
          end);
        end;
      until BytesRead = 0;
    finally
      DestStream.Free;
    end;
  finally
    SourceStream.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if FCopyThread = nil then
  begin
    FCopyThread := TCopyThread.Create('source.txt', 'dest.txt');
    FCopyThread.FreeOnTerminate := True;
    FCopyThread.Start;
    Button1.Caption := '取消';
  end
  else
  begin
    FCopyThread.Terminate;
    FCopyThread := nil;
    Button1.Caption := '开始';
  end;
end;

procedure TForm1.CopyProgress(const BytesCopied, TotalBytes: Int64);
begin
  // 更新进度显示
  Caption := Format('Copying %d/%d bytes', [BytesCopied, TotalBytes]);
end;

end.

ボタンクリックイベントでTCopyThreadオブジェクトを作成してスレッドを開始し、ファイルコピーを実行しています。TCopyThread.Executeメソッドでは、TFileStreamを使用してソースファイルの内容を読み取ってターゲットファイルに書き込んでいます。また、データの書き込みごとにSynchronizeメソッドを使用して、メインスレッドでプログレス表示を更新しています。

ウィンドウにボタンを置き、Button1ClickメソッドにボタンのOnClickイベントをバインドします。プログラムを実行すると、ボタンをクリックするとファイルのコピー操作を開始またはキャンセルできます。同時に、ウインドウのタイトルバーにはコピーの進捗状況がリアルタイムで表示されます。

大きなファイルをコピーする場合は、画面がフリーズすることがあります。これを防ぐために、コピー中にプログレスバーなどを用いて進捗状況を表示することを検討してください。

bannerAds