我有两个使用TCPServer和TCPClient组件相互通信的应用程序。
服务器以隐藏模式启动:Application.ShowMainForm: = false;
只有systemtray上的一个图标与用户交互。运行服务器之后,如果我运行客户端并连接到服务器这个冻结,但是如果我将服务器属性Application.ShowMainForm
更改为 true < / strong>一切都很完美。这是我正在使用的代码:
客户端应用
procedure TFormCliente.FormCreate(Sender: TObject);
begin
try
cliente.Connect;
except
hint1.ActivateHint(FormCliente,'Error.' + #13 +
'Verify if server is running','VCall',5000); //hint1 is a Jed component
end;
end;
服务器应用
[...]
private
FConexoes: TList;
[...]
type
PClient = ^TClient;
TClient = record
PeerIP : string[15]; { Client IP address }
HostName : String[40]; { Hostname }
Connected, { Time of connect }
LastAction : TDateTime; { Time of last transaction }
AContext : Pointer; { Pointer to thread }
end;
[...]
procedure TfrmServer.FormCreate(Sender: TObject);
begin
FConexoes := TList.Create;
end;
procedure TFrmServer.FormDestroy(Sender: TObject);
begin
FConexoes.Free;
end;
procedure TFrmServer.IdTCPServer1Connect(AContext: TIdContext);
var
NewClient: PClient;
begin
GetMem(NewClient, SizeOf(TClient));
NewClient.PeerIP := AContext.Connection.Socket.Binding.PeerIP;
NewClient.HostName := GStack.HostByAddress(NewClient.PeerIP);
NewClient.Connected := Now;
NewClient.LastAction := NewClient.Connected;
NewClient.AContext := AContext;
AContext.Data := TObject(NewClient);
ListView1.Items.Add.Caption:=NewClient.HostName;
end;
如果服务器表单可见,则客户端主机名将添加到列表视图中,但如果服务器表单不可见,并运行cliente和connect,则服务器会冻结,直到我终止客户端进程。任何人都可以帮助我吗?
答案 0 :(得分:1)
您在TListView
事件中直接访问OnConnect
不是线程安全的。这本身就可能导致死锁和崩溃。试试这个:
type
PClient = ^TClient;
TClient = record
PeerIP : string; { Client IP address }
HostName : String; { Hostname }
Connected, { Time of connect }
LastAction : TDateTime; { Time of last transaction }
AContext : Pointer; { Pointer to thread }
end;
procedure TFrmServer.IdTCPServer1Connect(AContext: TIdContext);
var
Client: PClient;
begin
New(Client);
try
Client.PeerIP := AContext.Connection.Socket.Binding.PeerIP;
Client.HostName := GStack.HostByAddress(Client.PeerIP);
Client.Connected := Now;
Client.LastAction := Client.Connected;
Client.AContext := AContext;
TThread.Synchronize(nil,
procedure
var
Item: TListItem;
begin
Item := ListView1.Items.Add;
Item.Data := Client;
Item.Caption := Client.HostName;
end
);
except
Dispose(Client);
raise;
end;
AContext.Data := TObject(Client);
end;
procedure TFrmServer.IdTCPServer1Disconnect(AContext: TIdContext);
var
Client: PClient;
begin
Client := PClient(AContext.Data);
AContext.Data := nil;
if Client = nil then Exit;
TThread.Synchronize(nil,
procedure
var
Item: TListItem;
begin
Item := ListView1.FindData(0, Client, True, False);
if Item <> nil then
Item.Delete;
end
);
Dispose(NewClient);
end;