关于 Indy 中 TIdTCPServer 在关闭时导致程序死机的Bug修复(delphi)

目录

 

一、bug症状

二、Bug存在的版本

三、Bug解决方案


一、bug症状

在使用indy的TIdTCPServer控件时,我们打开服务时会设置控件属性Active为True,关闭服务时自然是设置控件属性Active为False。当我们打开TIdTCPServer服务,如果有一些客户端已经连接上,此时如果我们需要关闭TCP服务时,自然会设置控件属性Active为False,,大概率会导致程序死机,非常恼人。此时需要手工关闭进程才可以重新启动。这样使用起来就很不方便,当然我们也可以通过别的办法回避(我们先一个一个线程关闭,然后再让Active设置为False就可以回避这个问题)。导致这个问题的原因是有几个客户端连接,就会有几个对应的服务线程服务客户端,此时TIdTCPServer在设置Active为False的时候并没有清除干净这些线程,线程列表清除有Bug,就会导致程序死机。

二、Bug存在的版本

我修复的是下面的版本,其它版本是否存在问题不得而知,同学们可以根据这个版本对比自己的版本进行修复!

修复后文件下载连接:IdScheduler.pas

delphi版本:

Indy版本:

三、Bug解决方案

查找indy的源程序文件IdScheduler.pas单元,在这个文件单元中,对文件进行修改,修改前和修改后的代码如下:

修改前代码(为了看清楚,我是用的是截图):

procedure TIdScheduler.TerminateAllYarns;
var
  i: Integer;
  LList: TIdYarnList;
begin
  Assert(FActiveYarns<>nil);

  while True do begin
    // Must unlock each time to allow yarns that are terminating to remove themselves from the list
    LList := FActiveYarns.LockList;
    try
      if LList.Count = 0 then begin
        Break;
      end;
      for i := LList.Count - 1 downto 0 do begin
        TerminateYarn(
          {$IFDEF HAS_GENERICS_TList}LList.Items[i]{$ELSE}TIdYarn(LList.Items[i]){$ENDIF}
        );
      end;
    finally
      FActiveYarns.UnlockList;
    end;
                                            
    IndySleep(500); // Wait a bit before looping to prevent thrashing
  end;
end;

 

修改后代码:

procedure TIdScheduler.TerminateAllYarns;
var
  i: Integer;
  LList: TIdYarnList;
begin
  Assert(FActiveYarns<>nil);

  while True do begin
    // Must unlock each time to allow yarns that are terminating to remove themselves from the list
    LList := FActiveYarns.LockList;
    try
      if LList.Count = 0 then begin
        Break;
      end;
      for i := LList.Count - 1 downto 0 do begin
        TerminateYarn(
          {$IFDEF HAS_GENERICS_TList}LList.Items[i]{$ELSE}TIdYarn(LList.Items[i]){$ENDIF}
        );
        //sensor 2019-06-12
        LList.Delete(i);   //增加了这一句,因为上面循环使用的是 downto 所以可以直接删除!!!!
      end;
    finally
      FActiveYarns.UnlockList;
    end;

    IndySleep(500); // Wait a bit before looping to prevent thrashing
  end;
end;

 

 

indy10.2.3 full 完全安装版 D7~2010 版本:indy10.2.3 经delphi7下的安装成功,delphi11和delphi6的安装没有试用 【自动安装】 Lib\Fulld7.bat 双击运行即可。 自动会把bpl文件拷到C:\windows\system32 重新打开delphi7会自动加载 dclIndyCore70.bpl dclIndyProtocols70.bpl 【手工安装】 1.windows的path路径增加D7的路径 在启用delphi7,要能加载dclIndyCore70.bpl这个文件 如果是自动安装,这个文件会拷到C:\windows\system32\dclIndyCore70.bpl,所以不用改path 2.delphi7菜单Library路径 添加indy10\LIB路径下的System、Core、Protocols下的三个目录 添加indey10\D7 因为这个目录下有bpl和dcu文件 3.删除delphi7目录Bin下的indy*.BPL文件,这是官方旧版本的文件,放心删除。 4.删除delphi7目录下的 Id*.DCU文件,一般都是在lib目录里。 5.打开indy10\lib目录,安装DPK包顺序如下: (1)编译 System\IndySystem70.dpk (只需要compile) (这个不是设计包,不需要install) (2)编译 Core\IndyCore70.dpk (只需要compile) 编译安装Core\dclIndyCore70.dpk (设计包,先complie后install) (3)编译 Protocols\IndyProtocols70.dpk (只需要compile) 编译安装Protocols\dclIndyProtocols70.dpk (设计包,先complie后install) 6.完成 【第二次手工安装】 第一步: indy10\D7目录下的5个文件 复制到delphiD:\Delphi7_Ent\Projects\Bpl IndySystem70.bpl IndyCore70.bpl IndyProtocols70.bpl dclIndyCore70.bpl dclIndyProtocols70.bpl 第二步: 打开delphi7菜单 Component/install packpages/ add dclIndyCore70.bpl 再 add dclIndyProtocols70.bpl 第三步 打开delphi7菜单Library路径 添加indy10\LIB路径下的System、Core、Protocols下的三个目录 完成!更简单。前提是要有现成bpl的文件,如果没有bpl文件,还得需要dpk编译
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海纳老吴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值