我正在使用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;