'Method called on thread using Synchronize does not return without moving the mouse

I have a unit and form which uses a worker thread to query a database. After each query is executed a method is called using Synchronize to update the UI.

It seems that whenever a call to the methods using Synchronize() is made, the process stops until I shake the mouse or interact with the keyboard.

Below is the basics of what I am doing. This example is complete other than that I did not provide a database connection or queries for a real database- I am hoping it will be enough to see the code.

A theory is that limiting the synchronize calls to one call at the end to update the entire UI will make this work, though I am not 100% on if or why this would help - something to do with not switching what the CPU is doing too often perhaps? It does not seem possible to have only one Synchronize given how I must iterate through different query results to populate the TListViews. I do want to keep using list views as shown and not change the method for displaying rows of data.

  unit ExampleCode;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, ADODB;

type
  TRefreshThread = class(TThread)
  public
  Procedure Execute; override;
  procedure UpdateLabel1;
  procedure UpdateLabel2;
  procedure UpdateLabel3;
  procedure UpdateLabel4;
  procedure populateListView1;
  procedure populatelistView2;
  procedure populatelistview3;
  procedure OnThreadTerminate(Sender : Tobject);
  constructor Create;
  end;

  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    ListView1: TListView;
    ListView2: TListView;
    ListView3: TListView;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
  end;

  var
  Form1: TForm1;
  RefreshThread : TRefreshThread;
  Query : TADOQuery;
  someDatabase : TADOConnection;

  implementation

   {$R *.dfm}

procedure TRefreshThread.UpdateLabel1;
begin

Form1.Label1.Caption := Query.FieldByName('Field1').AsString;

end;

procedure TRefreshThread.UpdateLabel2;
begin

Form1.Label1.Caption := Query.FieldByName('Field2').AsString;

end;


constructor TRefreshThread.Create;
begin

FreeOnTerminate := true;
OnTerminate := OnThreadTerminate;
inherited Create(false);

end;

procedure TRefreshThread.OnThreadTerminate(sender : TObject);
begin

sender := nil;

end;

procedure TRefreshThread.UpdateLabel3;
begin

Form1.Label1.Caption := Query.FieldByName('Field3').AsString;

end;

procedure TRefreshThread.UpdateLabel4;
begin

Form1.Label1.Caption := Query.FieldByName('Field4').AsString;

end;


procedure TRefreshThread.populateListView1;
var
Item1 : TListItem;
begin

Item1 := Form1.ListView2.Items.Add;
Item1.Caption := Query.FieldByName('Field5').AsString;
Item1.SubItems.Add(Query.FieldByName('Field6').AsString);
Item1.SubItems.Add(Query.FieldByName('Field7').AsString);

end;


procedure TRefreshThread.populateListView2;
var
Item1 : TListItem;
begin

Item1 := Form1.ListView2.Items.Add;
Item1.Caption := Query.FieldByName('Field8').AsString;
Item1.SubItems.Add(Query.FieldByName('Field9').AsString);
Item1.SubItems.Add(Query.FieldByName('Field10').AsString);


end;


procedure TRefreshThread.populateListView3;
var
Item1 : TListItem;
begin

Item1 := Form1.ListView2.Items.Add;
Item1.Caption := Query.FieldByName('Field11').AsString;
Item1.SubItems.Add(Query.FieldByName('Field12').AsString);
Item1.SubItems.Add(Query.FieldByName('Field13').AsString);

end;


procedure TRefreshThread.Execute;

begin


Query.Create(nil);

Query.Connection := SomeDatabase;

Query.SQL.Add('select FIELD1 from TABLE');

Query.Active := true;

Synchronize(UpdateLabel1);

Query.Close;
Query.SQL.Clear;

Query.SQL.Add('select FIELD2 from TABLE');

Query.Active := true;

Synchronize(UpdateLabel2);

Query.Close;
Query.SQL.Clear;


Query.SQL.Add('select FIELD3 from TABLE');

Query.Active := true;

Synchronize(UpdateLabel3);

Query.Close;
Query.SQL.Clear;

Query.SQL.Add('select FIELD4 from TABLE');

Query.Active := true;

Synchronize(UpdateLabel4);

Query.Close;
   Query.SQL.Clear;


   Query.SQL.Add('select FIELD5, Field6, Field7 from TABLE');

   Query.Active := true;

   try
   while not Query.Eof do
   begin
       Synchronize(PopulateListView1);
       Query.Next;
   end;
   finally
   Query.Close;
   Query.SQL.Clear;
   end;


   Query.SQL.Add('select FIELD8, Field9, Field10 from TABLE');

   Query.Active := true;


   try
   while not Query.Eof do
   begin
   Synchronize(PopulateListView2);
   Query.Next;
   end;
   finally
   Query.Close;
   Query.SQL.Clear;
   end;


Query.SQL.Add('select FIELD11, Field12, Field13 from TABLE');

Query.Active := true;


try
  while not Query.Eof do
begin
Synchronize(PopulateListView3);
Query.Next;
end;
finally
Query.Close;
Query.SQL.Clear;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

Timer1.Create(nil);
Timer1.Interval := 1000;
RefreshThread := TRefreshThread.Create();

end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin

if RefreshThread = nil then
RefreshThread := RefreshThread.Create();

end;

end.


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source