var
  cs:tcriticalsection;
implementation//tidtcpserver的execute 事件中的代码如下:
procedure TForm1.serverExecute(AThread: TIdPeerThread);
  var
    r_data:string;        //接收的字符串
    sl:tstringlist;       //分隔接收数据为各个字段
    lenstr:string;        //pklen:数据长度字段
    package_len:integer;  //数据包长度 = 去掉pklen字段以后的长度
  begin
    with athread.Connection do
      begin
        sl:=tstringlist.Create;   //创建tstringlist
        lenstr:= readstring(4);   //读取数据长度
        try
          package_len := strtoint(lenstr);
        except
          begin
           console.Lines.Add('接收数据长度错误!');
           exit ;
          end;
        end;
        r_data := readstring(package_len);    //读取数据包
        sl:= split(r_data,'|');               //将各个字段分解出来
        
        if sl.Strings[1] = '1111' then        //查询操作
          begin            
            cscx.Enter; //进入隔离区  
            try
               try
                 begin
                   query(sl.Strings[2],athread); //query为自定义函数,用adoquery查询
                 end
               except
                  .....
               end;
            finally
              cscx.leave;
            end;
         end;       
          freeandnil(sl);
      end;
  end;//query函数
query(data:string;athread:TIdPeerThread); 
  var
    data:string; //查询到的数据
  begin
    //进行数据库查询
    .......
    athread.connection.write(data);        
    .......
  end;
//因为使用adoquery对数据库进行查询,adoquery不是线程安全,所以用tcriticalsection进行线程保护,当多个客户端连接过来,并进行数据查询,运行一段时间以后,程序会出错,出错以后,客户端还可以连接上服务器端,经过多次测试,发现错误出在athread.connection.write(data)这一句,也就是说运行一段时间以后,会有向客户端发不出去数据的情况,造成一个线程卡在这里了,不能leave; 其它的线程就只能等。但是现在就是不知道,当write发送不出数据的时候,怎么办,是一直等,还是会引发什么异常?还是有其它的处理办法? 请大家帮帮忙
但不能再行数据查询了,这时当客户端再发查询的命令过来,就会运行到memo1.Lines.Add('1:-----进入保护区'+'); 这条语句就不再继续运行了? 不知道是什么原因,看上去像是cs.enter的时候出了错,但cs.enter的时候我进行了异常保护,但运行的时候没有捕年捉到异常信息,不知道是什么原因,请大家帮着看看代码!!!! 多谢  

解决方案 »

  1.   

    问题就出在你的查询互斥区,当服务器查询完成后给客户发送数据如果客户不及时读取数据,而服务器所发数据又填满了发送缓冲区就会导致阻塞,但并不是死锁,此时只要需要接收数据的客户及时接收数据就可以继续运行,但这就限制了客户的并发性。
    其实只用做一点调整就行了,你的查询做如下调整:
    query(data:string;athread:TIdPeerThread); 
      var
        data:string; //查询到的数据
      begin
        //.保护区开始......
        进行数据库查询
        数据打包到data中
        //.保护区结束......
        athread.connection.write(data);          end;