在intraweb usersession中实现服务器计时器的正确方法是什么

时间:2013-05-28 08:16:42

标签: delphi timer intraweb

我有一个简单的intraweb项目,具有以下结构

用户身份: 有一个计时器来检查数据库并加载更改,进行一些数据格式化并将结果放入内存表中。

MainForm: 有一个IWTimer来检查Usersession中的内存表是否已更改,并在需要时更新其内容。

我不使用IWTimer直接检查数据库,因为我不希望在浏览器中有一些影响用户体验的等待时间。

问题是usersession似乎没有消息队列,普通计时器不起作用。所以,我在Jedi VCL中使用了JvThreadTimer。我在UserSession.Create事件中创建它,并在Destroy Event中停止并释放它。它做得很好。

但是,当我关闭服务器应用程序时,它立即弹出EidClosedSocket并显示消息“Disconnected”。在MainForm / Usersession / ServerControl Unit中销毁事件之前触发了异常,因此在触发异常之前我找不到停止Timer的方法。

那么有没有一种正确的方法在usersession中设置服务器端计时器,还是有其他方式进行定期数据库检查而不影响浏览器的使用?

提前感谢您的帮助。

1 个答案:

答案 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已被处理的地方。