我的想法是使用 TDictionary 来管理 IdTCPServer 上的客户端连接。这是一个用于理解目的的简单示例代码(未经测试):
var
Dic: TDictionary<string, TIdContext>;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
Dic := TDictionary<string, TIdContext>.Create;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
Dic.Free;
end;
procedure TfrmMain.TCPServerConnect(AContext: TIdContext);
var
Hostname: string;
begin
Hostname := UpperCase(GStack.HostByAddress(AContext.Binding.PeerIP));
if not Dic.ContainsKey(Hostname) then Dic.Add(Hostname, AContext);
end;
procedure TfrmMain.TCPServerDisconnect(AContext: TIdContext);
var
Hostname: string;
begin
Hostname := UpperCase(GStack.HostByAddress(AContext.Binding.PeerIP));
if Dic.ContainsKey(Hostname) then
begin
Dic[Hostname].Free;
Dic.Remove(Hostname);
end;
end;
这段代码线程安全吗?
一句话:No.
如果您检查来源词典您应该很快意识到实现本身没有提供线程安全性。即使是这样,通过离散调用Dic例如,您有潜在的竞争条件需要应对:
if Dic.ContainsKey(Hostname) then
begin
// In theory the Hostname key may be removed by another thread before you
// get a chance to do this : ...
Dic[Hostname].Free;
Dic.Remove(Hostname);
end;
你需要自己利用Dic线程安全,幸运的是,在这种示例中,可以使用对象本身的监视器轻松实现这一点:
MonitorEnter(Dic);
try
if not Dic.ContainsKey(Hostname) then
Dic.Add(Hostname, AContext);
finally
MonitorExit(Dic);
end;
// ....
MonitorEnter(Dic);
try
if Dic.ContainsKey(Hostname) then
begin
Dic[Hostname].Free;
Dic.Remove(Hostname);
end;
finally
MonitorExit(Dic);
end;
如果您不熟悉 Delphi 中的监视器,简单来说,您可以将监视器视为一个随时可用的临界区,受每个TObject后代(在旧版本的 Delphi 中,不支持这些监视器,您可以通过显式关键部分实现相同的目标)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)