1

画面のスクリーンショットを毎秒数回撮る簡単なプログラムがあります。それを行う簡単なコードを作成しました。何度でも実行でき、問題なく動作します。しかし、同じコードをスレッドに入れて実行すると、アプリケーションがリソースを使い果たすまで (約 10 秒で) メモリ使用量が増加し始め、スレッドはもちろんスタックします。

テスト用に、2 つのボタンがあるフォームを用意しました。1 つは前述のコードを実行し、2 番目は同じコードを実行するスレッドを開始します。最初のボタンで Enter キーを押してもメモリ リークは発生しませんが、2 番目のボタンをクリックすると、スレッドは即座にメモリ使用量を増やし続けます (stop_thread 変数を使用して停止することもできますが、メモリ使用量は高いままです)。

...

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
  end;

var
  Form1: TForm1;
  stop_thread: Boolean;
  my_thread: TMyThread;

...

constructor TMyThread.Create();
begin
  inherited Create(true);
  FreeOnTerminate:=true;
  Suspended:=true;
end;

destructor TMyThread.Destroy;
begin
  inherited;
end;

procedure TMyThread.Execute;
var screen_bmp: TBitmap;
    desktop_hdc: HDC;
begin
  while(stop_thread=false)do
  begin
    screen_bmp:=TBitmap.Create;
    screen_bmp.PixelFormat:=pf32bit;
    screen_bmp.Height:=Screen.Height;
    screen_bmp.Width:=Screen.Width;
    desktop_hdc:=GetWindowDC(GetDesktopWindow);
    BitBlt(screen_bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, desktop_hdc, 0, 0, SRCCOPY);
    ReleaseDC(GetDesktopWindow, desktop_hdc);
    screen_bmp.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var screen_bmp: TBitmap;
    desktop_hdc: HDC;
begin
  screen_bmp:=TBitmap.Create;
  screen_bmp.PixelFormat:=pf32bit;
  screen_bmp.Height:=Screen.Height;
  screen_bmp.Width:=Screen.Width;
  desktop_hdc:=GetWindowDC(GetDesktopWindow);
  BitBlt(screen_bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, desktop_hdc, 0, 0, SRCCOPY);
  ReleaseDC(GetDesktopWindow, desktop_hdc);
  screen_bmp.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  stop_thread:=false;
  Button2.Enabled:=false;
  my_thread:=TMyThread.Create;
  my_thread.Resume;
end;

問題が BitBlt 行に関係していることはわかっています。BitBlt 行がないとメモリ リークがないからです。しかし、私は何が起こっているのか、なぜ起こっているのか理解できません。コードがメインスレッドから実行されているときに、なぜそれが起こらないのですか。Button1 コードをサイクルに入れてメイン スレッドからエンドレスに実行しても、メモリ使用量は低いままです。違いは何ですか?

アドバイスありがとうございます!

4

0 に答える 0