Multithreading 当线程调用Delphi XE2 GetTextExtentPoint32时失败
此简单示例在双击按钮1时引发异常(无效参数) 您可能需要多次单击才能获取消息 这个代码有什么问题Multithreading 当线程调用Delphi XE2 GetTextExtentPoint32时失败,multithreading,delphi,delphi-xe2,Multithreading,Delphi,Delphi Xe2,此简单示例在双击按钮1时引发异常(无效参数) 您可能需要多次单击才能获取消息 这个代码有什么问题 type TForm2 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); end; TTestThread = class(TThread) protected procedure Execute; override; end; var Form2:
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.
Windows GUI函数具有线程关联性。此约束将传递给VCL。这意味着您只能从主GUI线程访问VCL例程 在您的代码中,您通过从除主GUI线程之外的线程调用
Form2.Canvas.TextWidth
打破了这一规则。当该代码映射到Win32时,它最终使用与调用者的不同线程关联的设备上下文调用GetTextExtentPoint32
。那是违反规定的
解决办法是遵守规则。仅从主GUI线程调用VCL函数。Windows GUI函数具有线程关联性。此约束将传递给VCL。这意味着您只能从主GUI线程访问VCL例程 在您的代码中,您通过从除主GUI线程之外的线程调用
Form2.Canvas.TextWidth
打破了这一规则。当该代码映射到Win32时,它最终使用与调用者的不同线程关联的设备上下文调用GetTextExtentPoint32
。那是违反规定的
解决办法是遵守规则。只能从主GUI线程调用VCL函数。关于Delphi线程、VCL和TThread文档,甚至是由
File->New->Other->TThread单元创建的shell代码的每一篇文章都告诉人们“除非使用Synchronize,否则不要从线程访问可视化组件”,并且没有人愿意阅读它,并且问了同样的问题:“为什么当我从它里面访问可视化控件时,我的线程不能正常工作?”每一篇关于Delphi线程、VCL和TThread文档,甚至是由File->New->Other->TThread单元创建的TThread
shell代码的帖子都告诉人们“除非使用同步,否则不要从线程访问可视组件”,没有人会费心阅读它,并问同样的问题:“为什么当我从线程中访问可视控件时,我的线程不能正常工作?”+1正确,这是正确的。+1正确,这是正确的。