我有一个简单的intraweb项目,具有以下结构
用户身份: 有一个计时器来检查数据库并加载更改,进行一些数据格式化并将结果放入内存表中。
MainForm: 有一个IWTimer来检查Usersession中的内存表是否已更改,并在需要时更新其内容。
我不使用IWTimer直接检查数据库,因为我不希望在浏览器中有一些影响用户体验的等待时间。
问题是usersession似乎没有消息队列,普通计时器不起作用。所以,我在Jedi VCL中使用了JvThreadTimer。我在UserSession.Create事件中创建它,并在Destroy Event中停止并释放它。它做得很好。
但是,当我关闭服务器应用程序时,它立即弹出EidClosedSocket并显示消息“Disconnected”。在MainForm / Usersession / ServerControl Unit中销毁事件之前触发了异常,因此在触发异常之前我找不到停止Timer的方法。
那么有没有一种正确的方法在usersession中设置服务器端计时器,还是有其他方式进行定期数据库检查而不影响浏览器的使用?
提前感谢您的帮助。
答案 0 :(得分:0)
首先。不要在非窗口应用程序(如服务/网络服务器)中使用VCL内容和窗口句柄依赖。
满足该要求的最简单方法是使用带有事件对象的线程,该事件对象在应用程序启动时调度。
看起来应该是这样的:
type
TTimerThread = class(TThread)
private
fSig : TSimpleEvent;
procedure DoTimer;
protected
procedure Execute; override;
public
procedure SignalTerminate;
constructor Create;
destructor Destroy; override;
end;
{ TSessionGarbageCollector }
constructor TTimerThread .Create;
begin
fSig := TSimpleEvent.Create;
inherited Create(False);
end;
destructor TTimerThread.Destroy;
begin
fSig.Free;
inherited;
end;
procedure TTimerThread.Execute;
begin
try
// e.g. every 10 seconds
while fSig.WaitFor(10000) = wrTimeout do
begin
if Terminated then
break;
try
// #################################################
// #### Run the garbage collector from time to time
DoTimer;
except
on E : Exception do
begin
// your timer specific exception handling here
end;
end;
end;
except
on F : Exception do
begin
// your global exception handling here
end;
end;
end;
procedure TSessionGarbageCollector.DoTimer;
begin
// whatever you like your timer to do
end;
procedure TSessionGarbageCollector.SignalTerminate;
begin
Terminate;
fSig.SetEvent;
end;
另请注意,如果模块是dll(如isapi dll),则不应在初始化子句中调度线程。找一个你知道dllmain已被处理的地方。