0

この簡単な例では、Button1 をダブルクリックすると例外 (無効なパラメーター) が発生します。

メッセージを表示するには、数回クリックする必要がある場合があります。

このコードの何が問題になっていますか?

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

  TTestThread = class(TThread)
  protected
    procedure Execute; override;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var MyThread : TTestThread;
begin
  MyThread:=TTestThread.Create(true);
  MyThread.FreeOnTerminate:=True;
  MyThread.Priority:=tpHighest;
  MyThread.Resume;
end;

{ TTestThread }

procedure TTestThread.Execute;
var len : integer;
begin
 len := Form2.Canvas.TextWidth('test');
 if (len=0) then
  Raise Exception.Create(SysErrorMessage(GetLastError));
end;

end.
4

1 に答える 1

5

Windows GUI 関数にはスレッド アフィニティがあります。この制約は VCL に渡されます。つまり、メインの GUI スレッドからのみ VCL ルーチンにアクセスできます。

あなたのコードForm2.Canvas.TextWidthでは、メインの GUI スレッド以外のスレッドから呼び出して、このルールを破っています。そのコードが Win32 にマップされるとGetTextExtentPoint32、呼び出し元とは別のスレッドに関連付けられたデバイス コンテキストで呼び出すことになります。それはルールに反しています。

解決策は、規則に従うことです。メイン GUI スレッドからのみ VCL 関数を呼び出します。

于 2012-10-01T11:15:56.657 に答える