这个简单的例子在双击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.
答案 0 :(得分:5)
Windows GUI函数具有线程关联性。此约束将传递给VCL。这意味着您只能从主GUI线程访问VCL例程。
在您的代码中,您通过从主GUI线程以外的线程调用Form2.Canvas.TextWidth
来破坏此规则。当该代码被映射到Win32时,它最终使用与来自调用者的不同线程相关联的设备上下文调用GetTextExtentPoint32
。那是违反规则的。
解决方案是遵守规则。仅从主GUI线程调用VCL函数。