'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 |
|---|
