关于Indy线程与自定义ADO查询线程同步的苦恼(100分)

  • 主题发起人 rainqueen
  • 开始时间
R

rainqueen

Unregistered / Unconfirmed
GUEST, unregistred user!
用Indy10做了个IRC服务器,服务器接受客户端历史消息的查询响应,为及时客户端响应,在服务器的某个OnCommand事件中创建了一个单独的数据库查询线程(ADO方式,线程中TADOStoredProc直接根据ConnectionString建立独立的ADO连接,不采用公用方式),发现OnCommand事件中执行了QueryThread后自己继续干自己的事情,将事件参数中的AContext销毁了,导致QueryTread中无法再利用AContext发消息,请各位大虾帮忙,如何保证在CommandHandler在DoCommand后释放idCommand之前让QueryThread执行完。多谢多谢!
 
没人知道吗?自己顶一下。
 
OnCommand就是在线程中执行的,如果你需要执行什么操作就直接执行就行了,不需要担心什么,因为Indy的服务器端本身就是完全支持多线程的。
 
是的,Indy本身支持多线程。最初我在OnCommand中执行一个数据库查询时就是动态创建了一个TADOStoredProc,然后从数据库捞了数据后通过AContext.Context.Connection.SendCmd方式发给客户端。但实际测试发现客户端A、B同时发出查询请求,总有一个被阻塞掉,直到给其中一个发送完毕才去处理另一个。没办法才改成自己Create一个QueryThread的方式,结果.....。这块好像会涉及线程安全的,恳请帮忙。
 
假设QueryThread是执行完自动销毁的,那么在OnCommand中生成并启动这个线程,然后调用线程对象的WaitFor()方法,这时Indy线程会被阻塞住。
在QueryThread的execute方法中捞到数据后,把相关数据保存到变量中,然后再执行下去--也就是退出销毁自己了。
在QueryThread销毁的最后阶段,上面的Indy线程会重新唤起,然后读刚才那个变量,这时AContext对象还是存在的,任你怎么用。
 
szf,您好,按照您的方法我修改了实现方式,在OnCommand中子线程Create后执行了WaitFor,然后Terminate,这样倒是保证idCommand在子线程中可以用了,子线程执行结果也可以传递给主线程,但老问题出现了:由于WaitFor,并且子线程中有对服务端VCL组件MEMO的日志记录,A、B同时查询时总有一个被阻塞掉,又回到老路子上去了。
 
szf您好,非常抱歉,刚才我代码实现上有问题,在子线程中执行了Synchronize导致阻塞,去掉就可以了。非常感谢您的指导。
另外,最早Indy实现方式中的阻塞原因也找到了,为了节约连接时间,我虽然动态创建了TADOStoredProc,但为它的Connection指定了一个主线程的ADOConnection,Indy子线程销毁该ADOStoredProc时无法通知主线程的ADOConnection更新容器中的List列表,改成传递ConnectionString就可以了,不过会有连接开销。
再次感谢您的指导,我MSN:Powerdesigner@Hotmail.com,QQ:514248857,希望能联系。
 
请szf指点这两种实现方式哪种更好?个人觉得直接采用Indy的线程方式可能程序上可读性强一些。
 
哦,我也是顺着你的思路(另起数据库查询线程,并与之同步)下去才有这个结论的。
实际的应用中,如果数据库连接会根据运行线程频繁连接断开的话,根本没有必要使用那个多余的QueryThread,在OnCommand事件中,直接进行"连接-查询-断开"即可(正如zqw0117老兄所说的,Indy服务器已经是多线程了)。
要同时查询数据库,必须要有相应的并发连接--这个是常识啦。
所以连接池在某些应用条件下,是可以提高应用程序效率的,就是这个道理。
另外Synchronize的时机也要选择好,否则各个工作线程都是与主线程同步,就跟单线程差不多了--唯一的好处是界面不会冻结
 
OK,第一次做多线程,感谢指导!
 
我多次测试后发现增加QueryThread孙线程的方式每个Indy子线程获得的机会均等,服务器基本上会交替为各个Indy线程响应;而只采用Indy子线程并且通过AContext向客户端发消息时,服务器总是偏爱其中一个,其他偶尔才获得响应,通常都是A查询结果400个中返回了2、300个时,B才获得3、4次响应,非常稀罕,但当去掉AContext的SendCmd,不再向客户端发消息,OnCommand中只查询数据库并走游标时,每个Indy线程又可以交替获得响应,如果说AContext.Context.Connection.SendCmd会先阻塞再发送,那么为什么在QueryThread孙线程中就能交替呢?真是令人费解。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
顶部