我开发了一个连接到SQL Server数据库的应用程序,每隔1秒从表中读取一些数据
为此,我使用TTimer
,但数据库响应的延迟会影响我的应用程序性能。
我对Delphi中的TThread
了解一点,我现在想知道的是使用TTimer
和TThread
之间的区别?在这种情况下,使用TThread
代替TTimer
对我的应用程序性能有用吗?
答案 0 :(得分:3)
TTimer是一个基于消息的计时器。它将WM_TIMER消息发布到创建它的线程的消息队列中。您的数据库操作阻止该线程及时处理新消息。假设您的TTimer位于主UI线程中,这就是您的应用程序性能受损的原因。将数据库操作移动到工作线程可防止主线程的消息循环被阻止。
答案 1 :(得分:3)
两者之间的主要区别可以在他们的班级定义中找到:
TTimer = class(TComponent)
TThread = class
虽然TTimer
类扩展TComponent
并且是组件本身,但TThread
是一个扩展TObject
的抽象类。
TThread
公开了TThread.Sleep
之类的静态方法和一种名为Execute
的特殊保护方法,它必须在派生类中实现才能执行所需的工作。
TThread
直接使用来宾操作系统的Processes and Threads功能。
...为此我使用
TTimer
但数据库响应的延迟会影响我的应用程序性能
发生这种情况的原因是因为OnTimer
对象的TTimer
事件在调用线程中执行:将TTimer
组件放入表单并将其{{1实现了event,代码在主线程中执行。
OnTimer
方法更灵活:如果由于某种原因必须在主线程中执行代码,则可以实现在线程内TThread
嵌套Execute
TThread
方法。
如果您想在一段时间间隔后以重复方式执行数据库请求,最好考虑将TEvent
与TEvent
对象结合使用。
使用TMyThread = class(TThread)
private
FInterval: Integer;
FWaitEvent: TEvent;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create(Interval: Cardinal; CreateSuspended: Boolean);
destructor Destroy; override;
end;
的类定义示例:
constructor TMyThread.Create(Interval: Cardinal; CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FInterval := Interval;
FWaitEvent := TEvent.Create(nil, False, False, '');
end;
destructor TMyThread.Destroy;
begin
FWaitEvent.Free;
inherited;
end;
procedure TMyThread.TerminatedSet;
begin
inherited;
FWaitEvent.SetEvent;
end;
procedure TMyThread.Execute;
begin
inherited;
while not Terminated do begin
//do your stuff
//wait fo some amount of time before continue the execution
if wrSignaled = FWaitEvent.WaitFor(FInterval) then
Break;
end;
end;
已实施的课程:
WaitFor
FWaitEvent
对象上调用的TerminatedSet
方法允许等待所需的时间。
线程的FWaitEvent
方法的实现允许将class User
has_one :authenticity
end
class Authenticity
belongs_to :user
end
u = User.first
u.authenticate = Authenticate.create
对象置于信号状态,然后在间隔过去之前退出线程
答案 2 :(得分:3)
这并没有专门针对你的q,但正如对其中一个的评论所述 其他答案,以您正在进行的频率轮询数据库并不是一个好主意,特别是如果其他用户试图访问它。
有多种方法可以在数据更改时从数据库服务器获取通知,而无需不断地轮询它们。这篇Embarcadero论文对各种DBMS的可用内容进行了非常有用的回顾:
http://docwiki.embarcadero.com/RADStudio/XE8/en/Database_Alerts_%28FireDAC%29
如果您的Delphi版本包含FireDAC,您可以从链接中看到,如果您的DBMS支持,您可以使用TFDEventAlerter接收服务器上的数据更改通知 它
如果您使用的是Interbase或Firebird(可能还有其他一些),则可以使用其他Delphi组件,这些组件不需要FireDAC,例如:适用于Interbase的IBExpress ibrary中的TIBEventAlerter。
答案 3 :(得分:2)
如果您想要在主表单上
,我建议保留您的TTimer然后在你的TTimer中创建一个TTask
https://delphiaball.co.uk/2014/09/08/using-ttask-from-the-parallel-programming-library/
并且在那里完成所有数据库工作,但正如其他人建议每1秒检查一次并不是很好的做法。
这样的事情:
<tr ng-repeat="item in directiveinfo">
<td> {{item.name}} </td>
<td ng-repeat="(key,value) in item">
<input type=checkbox ng-model="value">
</td>
</tr>
Global var downloaddata : ITask
有更好的解决方案,这只是一个快速的基本答案,但它应该指导你做更好的事情。
在您的线程中执行逻辑将保持您的UI代表性,但要注意TThread.Syncronize将等待主窗体并根据情况TThread.queue将是一个更好的调用。
答案 4 :(得分:0)
无论使用TTimer还是TThread,建议仅运行查询以获取已更改的数据。为此,您需要:
第一次阅读后,索要新数据就足够了:
select c.* from 'customers' as c where c.modified > '2019...'
您一次读取所有数据,并将结果存储在临时内存阵列中。
关闭数据集>>后,将您与主数组进行比较(同步)。
要更新数据>>运行单独的SQL。