代码之家  ›  专栏  ›  技术社区  ›  Richard

在线程上使用Synchronize调用的方法在不移动鼠标的情况下不会返回

  •  -2
  • Richard  · 技术社区  · 8 年前

    似乎每当调用使用 Synchronize() 完成后,该过程将停止,直到我摇动鼠标或与键盘交互。

    一种理论是,将同步调用限制在最后一个调用以更新整个UI将使此工作正常,尽管我不完全了解这是否会有帮助,或者为什么会有帮助——这可能与不频繁切换CPU所做的事情有关吗?考虑到我必须迭代不同的查询结果来填充TListViews,似乎不可能只有一个Synchronize。我希望继续使用如图所示的列表视图,而不更改显示数据行的方法。

      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.
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Remy Lebeau    3 年前

    Synchronize() 将方法指针放入队列,然后等待主UI线程处理该队列。处理发生在RTL的内部 CheckSynchronize() 作用

    正如我在评论中所说 the question you linked to :

    检查同步() 也在以下情况下调用 TThread.WaitFor() 在主线程的上下文中调用,并且 每当主线程消息循环在处理消息队列中的所有挂起消息后处于空闲状态时 .

    正常地 同步() “唤醒”主UI线程,以防没有挂起的消息。RTL中有一个名为 WakeMainThread 哪一个 同步() 呼叫(如果已分配)。这允许主UI线程向自身发布消息,以便可以调用 检查同步() 越早越好。

    您描述的行为可能发生在以下可能的情况之一:

    1. 您的线程代码位于没有 TApplication 对象,它钩住 唤醒主线程 ,或者应用程序没有处理唤醒消息的消息循环。

    2. 您的代码位于GUI应用程序中,主UI线程中的某些内容阻止了它及时处理消息。

    3. 在以下情况下,主消息队列中没有挂起的消息 同步() 被调用,无论出于何种原因,都没有为其分配函数 唤醒主线程 ,因此主UI线程不接收 同步() 的唤醒请求,因此在最终收到新消息之前不会处理同步队列,如鼠标/键盘活动。

    您尚未提供有关应用程序或其设置的任何详细信息,因此无法诊断这些可能性中的哪些实际上影响了您的项目。