关于Indy服务器组件的多线程问题(200分)

  • 主题发起人 主题发起人 derl2003
  • 开始时间 开始时间
D

derl2003

Unregistered / Unconfirmed
GUEST, unregistred user!
在使用Indy的服务器组件比如IdPop3server,它为每一个连接分配了独立的线程。Idpop3server的事件过程里有个Athread的参数就是专门管理单个连接的独立线程。现在我
自己定义了一个计时器,想在计时器事件里控制这些线程,比如说断开某个连接应该该怎
么办?我现在是定义一个结构体,
PClient = ^TClient;
TClient = record
Name : String;

Lasttime : TDateTime;

Thread : Pointer;

end;
在Idpop3server某个事件过程里定义一个结构体变量,把AThread赋给它的Thread,然后
用一个TThreadlist 变量Clients来管理全部的连接的线程。
不过当我从中取出结构体的Thread,
with Clients.LockListdo
begin

.....
ActClient:=Items[x];//ActClient是结构体变量
Remove(ActClient);
RecThread:=TIdPeerThread(ActClient.Thread);
try
RecThread.Connection.Disconnect;//用了后会出现服务器异常且关不掉,说是中
止线程超时。
memo2.Lines.Add(ActClient.Username+' 会话超时!已断开。');
//FreeAndNil(RecThread);用这个的话出现异常,非法线程句柄,不过没有出现中
止线程超时的现象,服务器也可正常关闭,但我不知道线程是否真的释放了。
finally
FreeMem(ActClient);
end;
.....
end;
......
请高手赐教啊,还有我想问直接用Athread.Connection.Disconnect是否断开连接并释放管理该连接的线程?
虚心等候你的回答...
 
怎么没人回答啊,张无忌兄过来帮个忙呀
 
无忌满受欢迎的嘛~~~~~~~~
junhai@cmmail.com信得过发过来我帮你喽喽~~~~~~
 
不用Record类型似乎更好点
D6的Demo里有类似的
定义为
type
TSimpleClient = class(TObject)
Host,IP: string;
Thread: Pointer;
end;
Athread.Connection.Disconnect执行以后必须手动释放线程(在Server的OnDisconnect里写)
try
finally
AThread.Data := nil;
AThread.Free;
end;

RecThread:=TIdPeerThread(ActClient.Thread);//可能是这里有问题,你传过去的是值,不是地址
 
CSZ,谢谢你的回答啊,不过我按你说的在OnDisconnect里面加入了
try
finally
AThread.Data := nil;
AThread.Free;
end;
当我关闭整个程序的时候就会出现中止线程超时的错误而无法结束程序.
还有var RecThread:TIdPeerThread;
RecThread:=TIdPeerThread(ActClient.Thread);
应该得到的是一个指针或引用吧(我是这样想的)。
看了一下源码好像是用Threads来管理那些连接线程。看windows任务管理器如果在
Ondisconnect里手工释放Athread反而没有释放,每连接一次多一个线程,最后关闭程序
出现indy的中止线程超时异常,无法结束程序。因此我觉得这些连接线程在客服端主动断开
连接的情况下Indy会自动释放,现在就是对服务器端主动断开连接时应该怎样正确断开并释放该线程?如果从Threads里找出某个线程并直接使用SomeThread.connection.disconnect;
则关闭不了程序,会出现中止线程超时的异常错误。
请大家继续发表意见。
 
在初始化ActClient的时候
ActClient.Thread := AThread;

with Clients.LockListdo
begin

这句 Remove(ActClient);
不是已经将Thread从Server中删除了吗?
下一句 RecThread:=TIdPeerThread(ActClient.Thread);怎么还能取得值?
你跟踪一下,看看RecThread是不是已经是nil了?
 
derl2003,你的问题解决了吗?
我试了试,在Server的OnDisconnect改成一下就可以了
try
finally
ActClient.Free;
AThread.Data := nil;
end;
 
CSZ,Clientss是一个TThreadlist变量,Remove(ActClient);
只是经将ActClient从Clients中删除了,POPsserver管理的Threads里的线程没有动。
现在的问题是如何正确的控制并释放Indy服务器端对当前的客户端的连接线程。好像在OnDisconnect事件里不必手工释放,要释放也只能是释放自己分配的对象。
你写的Athread.Data:=nil 是什么意思,是不是这样就正确释放该线程了?
 
不好意思我和你做得有点不太一样
我没有var TThreadlist变量来保存各线程,只是用了TList来保存线程里的数据
只就是把把Athread.Connection里的数据保存到TList里
在客户端断开的时候我只要查找Tlist里Athead的Pointer,再将Tlist对应的Pointer Free
你看一下indy Demo里chat的Server代码
虽然是不同的控件不过对线程的控制应该是差不多的
 
我就是参照着那个demo的,不过我在自己的OnTimer事件里取出满足条件的线程的指针,
调用connection.disconnect 或者是connection.disconnectsocket都出现最后关闭不了程
序terminatethreadtimeout的异常,不过还是要谢谢你。分都给你啦。我又成为穷光蛋了
,哈哈。
 
我用indy的那个demo做了个服务器,后来当了indy9.0.13,也出现过terminatethreadtimeout异常,不过后来我不知道怎么改的弄好了
现在想找这个出错都找不到了呵呵
能不能把你主要出错的地方代码发一份给我,mycsz@163.com
 
对了你在对Threads.lockList进行操作后,应该调用Threads.UnlockList
再试试看吧
 
后退
顶部