2013-06-16 2 views
1

연결합니다. 서버는 숨겨진 모드에서 시작 : 나는 클라이언트를 실행하고 서버에이 동결을 연결하면 그냥를 SystemTray에 아이콘이 user.After와 상호 작용서버 동결 내가 사용하여 서로 tcpserver를하고하여 TcpClient 구성 요소와 통신이 응용 프로그램을

Application.ShowMainForm: = false;는, 서버를 실행하지만 서버 속성을 변경하는 경우 Application.ShowMainForm사실 모든 것이 완벽하게 작동합니다.

클라이언트 응용 프로그램 :

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; 

Server 응용 프로그램 : 서버 형태가 보이면

[...] 
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; 

, 클라이언트 호스트 이름이 추가됩니다 이것은 내가 사용하고 코드입니다 listview하지만 서버 양식이 보이지 않고 cliente를 실행하고 연결하면 클라이언트 프로세스가 종료 될 때까지 서버가 고정됩니다. 누구든지 나를 도울 수 있습니까?

+0

이 나를 위해 확인했다. 내 클라이언트 (예 : 연결이 끊긴)를 닫았지만 AContext.Data를 삭제하고 해당 문제를 해결하지 못하게 설정하면 예외가 발생합니다. 어쩌면 그것과 관련이 있습니다. – Jason

+3

Indy 이벤트는 다중 스레드이며 GUI를 메인 스레드가 아닌 다른 스레드에서 업데이트하지 않으려면 Synchronize() 호출을 사용하여 GUI를 업데이트해야합니다. – whosrdaddy

+0

Whosrdaddy 그래서 어떻게해야합니까? 스레드로부터 ButtonX.click을 넣는 것이 GUI 업데이트의 대안입니까? –

답변

1

OnConnect 이벤트에 TListView 귀하의 직접 액세스는 스레드 안전하지 않습니다. 그것 자체가 교착 상태와 충돌을 일으킬 수 있습니다. 대신이 시도 :

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;