0

我正在使用 Delphi XE6 和 UniDAC 和 MySQL

我的 DM 中有一些 TUniQuery 组件,我想反复刷新主题,所以我在我的主窗体中放置了一些计时器,并在每个计时器中创建一个线程并将查询传递给它以刷新数据:

例如 :

 TUpdateThread = class(TThread)
 private
  FQuery : TUniQuery;
  FResultHandle : THandle;
 public
  constructor Create(var Query : TUniQuery; ResultHandle : THandle);
 protected
  procedure Execute; override;
 end;

constructor TUpdateThread.Create(var Query: TUniQuery; ResultHandle : THandle);
begin
 inherited Create;
 Suspend;
 FQuery := Query;
 FResultHandle := ResultHandle;
 FreeOnTerminate := True;
 Resume;
end;

procedure TUpdateThread.Execute;
var
 Msg : String;
 B : Boolean;
begin
 try
  B := True;
  try
   FQuery.Refresh;
  except
   on E:Exception do
    begin
     B := False;
     Msg := 'Error : ' + #13 + E.Message;
     SendMessage(FResultHandle, MSG_UPDATERESULT, 2, Integer(Msg));
    end;
  end;
 finally
  if B = True then
   SendMessage(FResultHandle, MSG_UPDATERESULT, 1, 1);

  Terminate;
 end;
end;

有时它会成功完成,但很多时候我遇到了一些错误,例如 AVs 或“Net Pack Header ...”错误,或者有时我的网格(Ehlib DBGrid)有问题,例如绘制行错误或...(特别当我使用 DisableControls 和 EnableControls 时)所有查询都具有相同的连接,我认为每个线程都应该有自己的连接,因为所有计时器间隔都相同,我建议有时刷新查询会相互中断

实际上,我的数据库在 VPS 服务器中,并且有一些客户端应用程序,我想在 Clients 中有 Live-Tables 并重复更新主题

实现这一目标的最佳方法是什么?我应该如何在没有应用程序挂起的情况下更新我的表格!有一些组件如 TThreadTimer(或...),主题对这种情况有用吗?!

谢谢 ...

4

1 回答 1

1

第一个问题在这里:

constructor TUpdateThread.Create(var Query: TUniQuery; ResultHandle : THandle);
begin
 inherited Create;  // Create with no arguments 
 Suspend;           // means CreateSuspended = false
 FQuery := Query;
 FResultHandle := ResultHandle;
 FreeOnTerminate := True;
 Resume;
end;

在这里,您使用默认构造函数 ( CreateSuspended = false) 创建线程,线程立即开始运行。您立即调用suspend(已弃用且不应使用),但这仍然是一个竞争条件,因为您的线程可能会或可能不会Refresh在您分配之前开始尝试查询。要创建处于挂起状态的线程,请使用的重载构造函数

inherited Create(true);

Resume也已弃用。相反,您应该使用Start;.

此外,您将 a 传递TUniQuery给该线程的构造函数。我们可以假设,我想,这个查询与主线程有关联——也就是说,它(可能)是表单上的一个可视组件,具有与可视组件的数据绑定,或者与用户或用户交互界面。

如果是这样,答案是您根本无法做到这一点 - 一个线程无法修改与另一个线程具有亲和力的对象。例如,当后台线程同时销毁它们以准备刷新查询内容时,您的界面可能正在从查询中检索记录。这自然会引起各种问题。

简单的解决方案是使用常规计时器并在主线程上同步刷新。如果这需要太长时间,那么您需要完全考虑不同的策略。我们真的没有足够的信息来进一步提出建议。如果网络访问和 I/O 是瓶颈,那么您可能会考虑异步刷新到线程拥有的单独查询对象,然后将其同步分配给您的视图组件。

于 2015-09-22T11:45:03.483 回答