0

我有一个简单的内部网络项目,其结构如下

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

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

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

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

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

那么是否有适当的方法在 usersession 中设置服务器端计时器,或者是否有其他方法可以进行不影响浏览器使用的定期数据库检查?

提前感谢您的帮助。

4

1 回答 1

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

于 2013-05-28T13:34:15.190 回答