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
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...
Am I calling it wrong?
Code:
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;
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();
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.
This is possible to a call to SendMessage with 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;
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.
Example:
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With