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 回答