广播消息代码如下   
  list:=IdTCPSvr.Contexts.LockList;
   for i:=0 to lstPlayers.Count-1 do
   begin
      LContext:=TIdContext(item[i]);
      try
        LContext.Connection.IOHandler.WriteLn(str,TEncoding.UTF8);//str是已经设定好的数据
      except
        LContext.Connection.Disconnect;
      end;
   end;
   IdTCPSvr.Contexts.UnLockList;
在服务器端把某个用户发送给服务器的消息(str)再广播给所有的用户。假设有某个用户发生断网,那么与该用户对应的线程在执行 LContext.Connection.IOHandler.WriteLn(str,TEncoding.UTF8);就会发生错误,转而执行LContext.Connection.Disconnect;
但是该函数不能立刻触发ondisconnect事件,而是会延迟一段时间才触发该事件。并且在ondisconnect事件触发之前,服务器的其他广播线程都会出现停顿现象。也就是说如果某个用户发生网络中断一段时间后,其他所有的客户端都会有一小段时间,收不到服务器的广播消息,他们会一直等待,直到发生中断的线程执行完ondisconnect事件后,才会重新收到服务器端的消息。这个问题应该如何解决???

解决方案 »

  1.   

    我已经发现问题是出在这句话:LContext.Connection.IOHandler.WriteLn(str,TEncoding.UTF8);//str是已经设定好的数据
    当某个客户端断开的时候,这句话会阻塞所有其他线程的执行,怎么处理这个阻塞,有方法可以立刻解除吗??
      

  2.   

    我晕菜,线程是并发执行的
     list:=IdTCPSvr.Contexts.LockList;
      for i:=0 to lstPlayers.Count-1 do
      begin
      LContext:=TIdContext(item[i]);
      try
      假设你在此处做断开判断;
      LContext.Connection.IOHandler.WriteLn(str,TEncoding.UTF8);//str是已经设定好的数据
      except
      LContext.Connection.Disconnect;
      end;
      end;
      IdTCPSvr.Contexts.UnLockList;
    那么在你做判断的时候,也许网络还没有断开,而当执行到写函数的时候,网络才中断,所以阻塞的那句话还要被执行!
      

  3.   

    你把列表锁住了,去掉LContext.Connection.Disconnect;去掉LockList试试
      

  4.   

    楼上说的方法,我已经试过,无论是否执行LContext.Connection.Disconnect,还是去掉LockList都没有用,但是上面的程序在2个用户登录的时候,当其中一个用户断开连接的时候,服务器是不发生发送延时的,但是当客户端增加到3个或以上的时候,就会发生延时。
    如果把Connection.Disconnect放到主线程中执行,就不会发生相应的广播发送延时。