-1

在这段代码中,正如您在 Connect 上看到的那样,AContext.Data 填充了一些东西

TmyTThreadList = class(TThreadList)
  id: integer;
end;

var unique_id:integer;

procedure TfrmTestIdTCPServer.IdTCPServerConnect(AContext: TIdContext);
 begin
  CS.Enter;
  try
    inc(unique_id);
  finally
    CS.Leave;
  end;

   AContext.Data := myTThreadList.Create;
   list := myTThreadList(AContext.Data).LockList;
   try
     myTThreadList(AContext.Data).id := my_unique_id;
     list.Add(myTThreadList(AContext.Data));
   finally
     myTThreadList(AContext.Data).UnlockList;
   end;
 end;

然后在断开连接时,编码器在这里检查 Acontext.Data <> nil

procedure TfrmTestIdTCPServer.IdTCPServerDisconnect(AContext: TIdContext);
 var
 begin
   if AContext.Data <> nil then
   begin

问题是,他为什么要检查 nil ?

谢谢。

编辑:

我问这个,因为当我做同样的事情时, onExecute 我访问 AContext.Data ,有时(当同时连接许多客户端时) AContext.Data 为空,出现访问冲突。

4

2 回答 2

0

最初的程序员可以出于多种不同的原因检查 Data 是否为 nil,真正知道这一点的唯一方法是问他/她为什么这样做。

我认为可能是:

  • 即使为任何连接创建了一个新的Data对象,这个对象也可以在连接的生命周期内被释放,出于任何其他数量或原因。例如,由于存储在那里的数据或来自客户端或其他外部源的请求,在该服务器组件的 OnExecute 事件处理程序中。
  • 也许在连接的生命周期内要执行的代码超出了原始程序员的控制,所以他/她没有其他方法可以知道 Data 对象是否仍然存在,例如组件编写者应该进行那种测试,或者一个在团队中工作的图书馆程序员。
  • 最初的编码员只是那种防御性的程序员,即使他/她知道 Data 对象应该在那里,也正在应用检查,但只是为了确保它存在并防止意外的访问冲突。

至于您所关心的,AFAIK,Indy 不会触及 Data 对象,而是在 Task 实例的 Destroy 序列中。

TIdTask.Data文档指出:

用户指定的对象,其值在任务执行期间使用。Data 是一个 TObject 属性,表示用户指定的对象实例,其值可在任务执行期间使用。

在 Create 中创建任务后,必须将对象实例分配给 Data。

Data 属性归 TIdTask 实例所有,将在 Destroy 中释放。

并且没有提及 Indy 本身释放数据的任何情况。

我做了一个测试,将一个对象分配给一个新连接,在服务器中对其进行一些工作并从客户端进行多个连接,并且在数千个连接之后,没有人未能保持正确的 Data 对象附加到每个 AContext调用,不仅对 OnDisconnect,而且对 OnExecute 事件。

于 2012-11-26T06:23:45.337 回答
0

OnConnect如果事件处理程序中发生未捕获的异常,OnDisconnect仍然可以调用该事件。如果到那时引发异常,TThreadList.CreateAContext.Data不会分配。

于 2012-11-26T22:12:40.920 回答