陷入dbx DataSnap用户会话的消息循环 [英] Hooking into message loop of dbx DataSnap user session

查看:85
本文介绍了陷入dbx DataSnap用户会话的消息循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有办法挂接到dbx用户会话的WndProc?

Is there a way to hook into the WndProc of a dbx user session?

背景:
dbx DataSnap使用Indy组件进行TCP通信。以最简单的形式,DataSnap服务器是一个接受连接的Indy TCP服务器。建立连接后,Indy为该连接创建一个线程,该线程处理对该连接的所有请求。

Background: dbx DataSnap uses Indy components for TCP communication. In its simplest form, a DataSnap server is an Indy TCP server accepting connections. When a connection is established, Indy creates a thread for that connection which handles all requests for that connection.

这些用户连接中的每一个都消耗资源。对于同时具有数百个连接的服务器,这些资源可能会很昂贵。许多资源可以合并,但是我不想每次都需要时总是获取和释放资源。

Each of these user connections consume resources. For a server with a couple hundred simultaneous connections, those resources can be expensive. Many of the resources could be pooled, but I don't want to always acquire and release a resource each time it is needed.

相反,我想实现空闲计时器。线程完成资源处理后,计时器将启动。如果线程在计时器过去之前访问资源,则该资源仍将分配给该线程。但是,如果计时器在下一次访问之前过去,则资源将释放回池中。下次线程需要资源时,将从池中获取另一个资源。

Instead, I'd like to implement a idle timer. After a thread finishes with a resource, the timer would start. If the thread accesses the resource before the timer has elapsed, the resource would still be "assigned" to that thread. But if the timer elapses before the next access, the resource would be released back to the pool. The next time the thread needs the resource, another resource would be acquired from the pool.

我还没有找到一种方法。我尝试使用SetTimer,但是我的计时器回调从未触发。我认为这是因为Indy的线程的WndProc没有调度WM_TIMER。我无法控制此线程的执行循环,因此无法轻松查看事件是否已发出信号。实际上,除非该线程正在处理用户请求,否则我的该线程代码均不会执行。实际上,我想让代码在任何用户请求之外执行。

I haven't found a way to do this. I've tried using SetTimer but my timer callback never fires. I assume this is because Indy's WndProc for the thread isn't dispatching WM_TIMER. I have no control of the "execution loop" for this thread, so I can't easily check to see if an event has been signaled. In fact, none of my code for this thread executes unless the thread is handling a user request. And in fact, I'm wanting code to execute outside of any user request.

对原始问题的解决方案或其他方法的建议也将同样受到赞赏。

Solutions to the original question or suggestions for alternative approaches would be equally appreciated.

推荐答案

James L可能已将其钉牢。由于Indy线程没有消息循环,因此您必须依靠另一种机制-如只读线程本地属性(例如,他的计算机中的 UserCount 和/或 LastSeem 示例)-并使用服务器的主线程运行TTimer以释放给定规则的资源。

James L maybe had nailed it. Since Indy thread does not have an message loop, you have to rely in another mechanism - like read-only thread-local properties (like UserCount and / or LastSeem in his' example) - and using main thread of the server to run a TTimer for liberating resources given some rule.

编辑:另一个想法是创建一个通用数据结构(下面的示例),该结构在线程每次完成其工作时都会更新。

another idea is create an common data structure (example below) which is updated each time an thread finishes its' job.


警告:仅从头脑中进行编码...可能无法编译...;-)

WARNING: coding from mind only... It may not compile... ;-)

示例:

TThreadStatus = (tsDoingMyJob, tsFinished);

TThreadStatusInfo = class
private
  fTStatus : TThreadStatus;
  fDTFinished : TDateTime;
  procedure SetThreadStatus(value: TThreadStatus);
public
  property ThreadStatus: TThreadStatus read fTStatus write SetStatus;
  property FinishedTime: TDateTime read fDTFinished;
  procedure FinishJob ;
  procedure DoJob;
end

procedure TThreadStatusInfo.SetThreadStatus(value : TThreadStatus)
begin
  fTStatus = value;
  case fTStatus of 
    tsDoingMyJob :
       fDTFinished = TDateTime(0);
    tsFinished:
       fDTFinished = Now;
  end;
end;

procedure TThreadStatusInfo.FinishJob;
begin
  ThreadStatus := tsFinished;
end;

procedure TThreadStatusInfo.DoJob;
begin
  ThreadStatus := tsDoingMyJob;
end;

将其放入列表(您喜欢的任何列表类)中,并确保每个线程都已关联
在该列表中具有索引。仅当您不再使用
个线程数量(缩小列表)时,才从列表中删除项目。在创建新线程
时添加一个项目(例如,您有4个线程,而现在需要第5个线程,则在主线程上创建一个新项目)。

Put it in a list (any list class you like), and make sure each thread is associated with a index in that list. Removing items from the list only when you won't use that number of threads anymore (shrinking the list). Add an item when you create a new thread (example, you have 4 threads and now you need an 5th, you create a new item on main thread).

由于每个线程在列表中都有一个索引,因此您无需封装此写操作(
在TCriticalSection上调用T

Since each thread have an index on the list, you don't need to encapsulate this write (the calls on T on a TCriticalSection.

您可以轻松阅读此列表,在主线程上使用TTimer检查
每个线程的状态,因为您有每个线程的完成时间
您可以计算超时时间。

You can read this list without trouble, using an TTimer on main thread to inspect the status of each thread. Since you have the time of each thread's finishing time you can calculate timeouts.

这篇关于陷入dbx DataSnap用户会话的消息循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆