多线程 – 如何使用Delphi从Thread更新GUI

前端之家收集整理的这篇文章主要介绍了多线程 – 如何使用Delphi从Thread更新GUI前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用Delphi匿名线程来执行代码.
在线程的中间,必须进行一些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;

猜你在找的Java相关文章