我正在使用Delphi匿名线程来执行代码.
在线程的中间,必须进行一些GUI更新,一些标签更改等.
在线程的中间,必须进行一些GUI更新,一些标签更改等.
如果我从线程内部执行此操作,则会发生更改,但一旦线程停止.他们消失了,然后应用程序给我旧的窗口处理程序错误…(这是预期的)
系统错误.编号:1400.窗口句柄无效
我尝试使用Syncronize(updateui);执行更改的方法(将它们移动到一个单独的函数),但我在syncronize E2066 Missing操作符或分号上得到一个错误,这对我来说根本没有意义……
我一页又一页地搜索过,他们似乎都这么称呼它,但是当我这样做时,我得到了上述错误……
我说错了吗?
码:
TThread.CreateAnonymousThread(
procedure
begin
main.Enabled:=false;
Loading.show;
label52.caption:=getfieldvalue(datalive.users,'users','credit_amount','user_id',user_id );
CoInitialize(nil);
if (length(maskedit1.Text)=maskedit1.MaxLength) and (pingip(serverip)=true) then
begin
if (strtofloat(label52.caption)>0) then
begin
....do some work....
Synchronize(updateui);
end
else Showmessage('Insufficient Funds. Please add funds to continue.');
end
else if (length(maskedit1.Text)<>maskedit1.MaxLength) then
begin
Showmessage('ID Number not long enough.');
end
else
begin
Showmessage('Could not connect to the server. Please check your internet connection and try again.');
end;
CoUnInitialize;
loading.close;
main.Enabled:=true;
end).start;
UpdateUI:
procedure TMain.updateui; var birthdate,deathdate:TDate; begin Panel3.Show; Label57.Caption := 'Change 1'; Label59.Caption := 'Change 2'; Label58.Caption := 'Change 3'; Label60.Caption := 'Change 4'; Label62.Caption := 'Change 5'; Label70.Caption := 'Change 6'; ScrollBox1.Color := clwhite; end;
解决方法
使用TThread.Synchronize并传递另一个匿名函数.然后你可以在匿名函数中调用updateui:
TThread.CreateAnonymousThread(
procedure
begin
// do whatever you want
TThread.Synchronize(nil,procedure
begin
updateui();
end);
// do something more if you want
end
).Start();
同步通常很昂贵(关于性能).只有在他们真正需要的时候才能做到.如果扩展updateui方法以减少绘制操作,则可以提高性能.
这可以通过WM_SETREDRAW调用SendMessage:
procedure StopDrawing(const Handle: HWND); const cnStopDrawing = 0; begin SendMessage(Handle,WM_SETREDRAW,cnStopDrawing,0); end; procedure ContinueDrawing(const Handle: HWND); const cnStartDrawing = 0; begin SendMessage(Handle,cnStartDrawing,0); // manually trigger the first draw of the window RedrawWindow(Handle,nil,RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN); end;
在updateui()的顶部添加对StopDrawing()的调用,并在updateui()的末尾调用ContinueDrawing().对ContinueDrawing()的调用应该在finally-block中.这将确保即使在执行updateui期间发生异常之后也会绘制窗口.
例:
procedure TMain.updateui;
begin
try
StopDrawing(Handle);
Panel3.Show;
Label57.Caption := 'Change 1';
Label59.Caption := 'Change 2';
// ...
finally
// Code under finally gets executed even if there was an error
ContinueDrawing(Handle);
end;
end;