求高人指点:多线程处理队列数据的问题 !!!(100分)

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

RoninHao

Unregistered / Unconfirmed
GUEST, unregistred user!
我用的indy9的TIdtelnet控件,在他的IdTelnet1DataAvailable事件中,如果每收到一行回显的字符串就把这一行字符串加入一个TStringList中去,然后另起一个线程专门负责从这个 stringlist中读数据分析,分析完后删除一行,具体线程中的代码是这样的
分析线程
while (true)do
begin
while (strlist.count>0)do
begin

AnalysString2(strlist.Strings[0]);
strlist.Delete(0);
end;
sleep(500);
end;

在分析线程中针对获取的字符串在分析并生成sql语句,插入一个sqllist的队列
专门再有一个写数据库的线程负责从sqllist中读取sql语句进行写库操作
写数据库线程代码如下:
while(true)do
begin
if (sqllist.count>0) then
begin
EnterCriticalSection(CriticalSection) ;
ADOQuery.SQL := sqllist;
sqllist.Clear;
LeaveCriticalSection(CriticalSection);
ADOQuery.ExecSQL;
ADOQuery.SQl.Clear;
end;
sleep(500);
end;
不停的去读sqllist,如果有数据就拿过来写库,然后把sqllist清空
整个处理流程如下:
TIdTelnet控件发送一个命令后,就不停的接受回显的字符串,字符串接受的速度有时候快有时候慢,我把接受到的字符串存入一个TStringList,然后起一个线程不停对这个stringlist第一行的数据读出来分析,分析完后删除;并在分析线程中会生成sql语句,插入到一个Tstringlist类型的sqllist中,另外再有一个写库线程读这个sqllist完成写库操作
请问我上面的处理方法有什么不妥的和会造成出错的地方,或者大家有神么更好的处理方法么?我总感觉我这个会出问题但是又想不起来要怎么搞,谢谢大家
 
应该没有问题,我们公司和你的过程类似
我们的处理过程是向下位机发送命令,并不是立即发送,而是保存到一个队列中TList,线程对TList进行读取命令,然后依次发送到下位机。
我觉得你的代码不是很安全,最好加try..except保护。
1.如果线程出现异常怎么办?比如系统会抛出一个异常的对话框,若一直有异常则一直有对话框出现,造成死机.
2.两次响应SQL语句之间是否要适当延时,给数据库引擎足够的反应时间?
3.若本次因为各种原因数据库没有响应你的SQL语句,是否要重新发送一次避免丢包?但是也不能重复发送次数太多避免死循环
个人意见供参考
 
to muhx : 谢谢,我用TStringList做对列,接受字符串时是不停的往在后面追加,线程中处理完字符串后就删除最前面那个,不知道如果不作同步处理的话会不会出问题
 
运行一段时间后分析线程就死在哪里了,字符串接受一直在继续。。还没找到原因。。
 
我的队列处理的一段代码,希望对你能有帮助
使用临界区进行同步
TCmdQueue = class
private
FCriticalSection: TCriticalSection;
FCmdList: TList;
function GetCmdCount: Integer;
public
constructor Create;
destructor Destroy;
override;
public
procedure Lock;
procedure Unlock;
procedure ClearQueue;
procedure PushCmd(const ACmdParam: TCmdParam);
function PopCmd: PCmdParam;
property cqCount: Integer read GetCmdCount;
end;

.........................
implementation
{ TCmdQueue }
{ 创建命令队列类 }
constructor TCmdQueue.Create;
begin
inherited Create;
FCriticalSection := TCriticalSection.Create;
FCmdList := TList.Create;
end;

{ 释放命令队列类 }
destructor TCmdQueue.Destroy;
begin
ClearQueue;
FCmdList.Free;
FCriticalSection.Free;
inherited;
end;

{ 清空命令队列,回收内存 }
procedure TCmdQueue.ClearQueue;
var
i: Integer;
tmpPCmd: PCmdParam;
begin
Lock;
try
if FCmdList.Count <= 0 then
Exit;
for i := FCmdList.Count - 1do
wnto 0do
begin
tmpPCmd := PCmdParam(FCmdList.Items);
Dispose(tmpPCmd);
FCmdList.Delete(i);
end;
finally
UnLock;
end;
end;

{ 获取命令队列中的命令数量 }
function TCmdQueue.GetCmdCount: Integer;
begin
Lock;
try
Result := FCmdList.Count;
finally
UnLock;
end;
end;

{ 弹出命令队列队首 }
function TCmdQueue.PopCmd: PCmdParam;
begin
Lock;
try
Result := nil;
if FCmdList.Count <= 0 then
Exit;
Result := PCmdParam(FCmdList.Items[0]);
FCmdList.Delete(0);
finally
Unlock;
end;
end;

{ 将命令压进命令队列 }
procedure TCmdQueue.PushCmd(const ACmdParam: TCmdParam);
var
tmpPCmd: PCmdParam;
begin
Lock;
try
New(tmpPCmd);
Move(ACmdParam, tmpPCmd^, SizeOf(TCmdParam));
FCmdList.Add(tmpPCmd);
finally
Unlock;
end;
end;

{ 进入临界区 }
procedure TCmdQueue.Lock;
begin
FCriticalSection.Enter;
end;

{ 退出临界区 }
procedure TCmdQueue.Unlock;
begin
FCriticalSection.Leave;
end;
 
我觉得不需要TstringList;因为在删除第一个的delete(0)的时候会出现大量内存操作,
改用指针链,这样处理速度快.
 
谢谢你了,我有个问题想请教一下,就是TIdTelnet这个控件接受回显字符串的时候是同步还是异步的,我就担心如果分析线程对字符串队列加锁之后,接受会有问题
 
TIdTelnet这个控件我不熟悉,楼主还是查一下资料
 
现在分析和入库已经没问题了,问题是我用的indy9哪个Tidclien空间接收字符串每次运行了几个小时她就自动停了。。好郁闷。。
 
问题是这样的,我telnet登陆上一台服务器后,运行一个命令,类似more的,它就源源不断的反回字符串回来,我就是接受这个,现在是运行了几个小时以后,接收就停了。不知道怎么回事。。会不会是linux服务器那边主动断开了
 
接受答案了.
 
后退
顶部