如何使用Delphi从线程更新GUI [英] How to update GUI from Thread using Delphi

查看:482
本文介绍了如何使用Delphi从线程更新GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Delphi匿名线程执行代码. 在线程中间,必须进行几次GUI更新,更改一些标签,等等.

I am using Delphi anonymous thread to execute code. In the middle of the thread, a couple of GUI updates have to take place, a couple of labels changing etc.

如果我从线程内部执行此操作,则会进行更改,但是只要线程停止就进行更改.它们消失了,然后应用程序给了我旧的窗口处理程序错误...(这是可以预料的)

If I do this from inside the thread, the changes take place, but as soon as the thread stops. they disappear, and then the application gives me the old window handler error...(Which is to be expected)

System Error. Code:1400. Invalid window handle

我尝试使用Syncronize(updateui);方法执行更改(将更改移至单独的功能),但是在同步E2066 Missing operator or semicolon上收到错误,这对我根本没有意义...

I tried using the Syncronize(updateui); method to execute the changes(moved them to a separate function), but I get an error on the syncronize E2066 Missing operator or semicolon which does not make sense to me at all...

我已经一页接一页地搜索了,他们似乎都这样称呼,但是当我这样做时,我得到了上面的错误...

I have searched through page after page, and they all seem to call it this way, but when I do, I get the above error...

我说错了吗?

代码:

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 :

Use TThread.Synchronize and pass another anonymous function to it. Then you can call updateui in the anonymous function:

TThread.CreateAnonymousThread(
  procedure
  begin
    // do whatever you want

    TThread.Synchronize(nil,
      procedure
      begin
        updateui();
      end);

   // do something more if you want
  end
).Start();

同步通常很昂贵(就性能而言).仅在确实需要它们时才使用它们.如果扩展 updateui 方法以减少绘制操作,则可以提高性能.

Synchronizations are generally expensive (regarding performance). Only do them when they are really neccessary. You can increase the performance if you extend the updateui-method to reduce paint-operations.

可以调用 WM_SETREDRAW :

procedure StopDrawing(const Handle: HWND);
const
  cnStopDrawing = 0;
begin
  SendMessage(Handle, WM_SETREDRAW, cnStopDrawing, 0);
end;

procedure ContinueDrawing(const Handle: HWND);
const
  cnStartDrawing = 1;
begin
  SendMessage(Handle, WM_SETREDRAW, cnStartDrawing, 0);

  // manually trigger the first draw of the window
  RedrawWindow(Handle, nil, 0,
    RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
end;

updateui()顶部添加对 StopDrawing()的调用,并在< updateui().对 ContinueDrawing()的调用应位于最后-block .这样可以确保即使在执行updateui期间发生异常之后,窗口也将被绘制.

Add a call to StopDrawing() at the top of updateui() and a call to ContinueDrawing() at the end of updateui(). The call to ContinueDrawing() should be in a finally-block. This will ensure that the window will be painted even after an exception has occured during the execution of 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;

这篇关于如何使用Delphi从线程更新GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆