2011-08-01 8 views
3

비동기 CTP 프레임 워크에서 연습을하고 연습으로 임의의 프로토콜을 사용하여 서버를 쿼리 할 수있는 TCP 클라이언트를 만듭니다. 어쨌든, 아주 초기 단계에서 연결 문제 때문에 붙어 있습니다. 나는 아직도 약간의 기본 점을 이해하지 못했거나 이상한 것이있다. 다음, 후속 쿼리 (코드가 아닙니다 여기에 표시)에 사용할 TcpClient 인스턴스를 다시 가지고,비동기 TCP 클라이언트 연결에서 전화 끊기

public class TaskClient 
{ 
    public static Task<TcpClient> Connect(IPEndPoint endPoint) 
    { 
     //create a tcp client 
     var client = new TcpClient(AddressFamily.InterNetwork); 

     //define a function to return the client 
     Func<IAsyncResult, TcpClient> em = iar => 
     { 
      var c = (TcpClient)iar.AsyncState; 
      c.EndConnect(iar); 
      return c; 
     }; 

     //create a task to connect the end-point async 
     var t = Task<TcpClient>.Factory.FromAsync(
      client.BeginConnect, 
      em, 
      endPoint.Address.ToString(), 
      endPoint.Port, 
      client); 

     return t; 
    } 
} 

내가 한 번만이 함수를 호출하는 것을 의미 :

그래서, 여기에 비동기 커넥터입니다.

//this method runs on the UI thread, so can't block 
    private void TryConnect() 
    { 
     //create the end-point 
     var ep = new IPEndPoint(
      IPAddress.Parse("192.168.14.112"), //this is not reachable: correct! 
      1601); 

     var t = TaskClient 
      .Connect(ep) 
      .ContinueWith<TcpClient>(_ => 
      { 
       //tell me what's up 
       if (_.IsFaulted) 
        Console.WriteLine(_.Exception); 
       else 
        Console.WriteLine(_.Result.Connected); 

       return _.Result; 
      }) 
      .ContinueWith(_ => _.Result.Close()); 

     Console.WriteLine("connection in progress..."); 

     //wait for 2" then abort the connection 
     //Thread.Sleep(2000); 
     //t.Result.Client.Close(); 
    } 

시험은 원격 서버에 연결을 시도하는 것입니다,하지만 (에 PC를하지만, 서비스가 중지)에 도달 할 수 있습니다

어딘가에 내 양식에, 나는 기능을 다음과 같이 위의 호출.

TryConnect 함수를 실행할 때 곧바로 "연결 진행 중 ..."을 반환하고 원격 끝 점이 해제되어 있으므로 예외를 표시합니다. 우수한!

문제는 예외를 반환하는 데 몇 초가 걸리므로 진행중인 작업을 취소 할 수있는 기회를 사용자에게 제공하고 싶습니다. BeginConnect 메서드에 대한 MSDN 사양에 따르면 비동기 작업을 중단하려면 작동중인 소켓에서 Close를 호출하면됩니다.

그래서 2 초 후에 사용자 취소를 시뮬레이트하기 위해 위에서 두 줄을 추가하려고했습니다 (위와 같이 주석 처리 됨). 결과는 앱 (모래 시계)이 멈추는 것처럼 보입니다. IDE를 일시 정지하면 마지막 행인 t.Result.Client.Close()에서 멈 춥니 다. 그러나 IDE를 중지하면 예외없이 모든 것이 정상적으로 종료됩니다.

나는 또한 클라이언트를 직접 t.Result.Close()으로 닫으려고했으나 정확히 동일합니다.

나야, 아니면 연결 프로세스가 망가 졌나요?

미리 감사드립니다.

답변

1

개체에 Dispose()을 호출 해보세요. Close()보다 조금 공격적입니다. TcpClient 클래스의 여러 Timeout 멤버를보고 더 적절한 값으로 설정할 수 있습니다 (예 : LAN 환경에서 1 초 정도면 충분). .Net 4.0의 CancellationTokenSource 기능을 살펴볼 수도 있습니다. 이렇게하면 Task에 신호를 보내서 신호를 멈추게 할 수 있습니다. 시작했을 수도있는 article을 발견했습니다.

실제로 스레드가 멈추는 지 확인해야합니다 (기본 스레드가 정지 된 다른 스레드를 기다리고있을 수도 있음). .ContinueWith(_ => _.Result.Close())이 문제 일 수 있습니다 (소켓을 두 번 닫을 때의 동작을 확인해야합니다). 디버깅하는 동안 스레드 창 (디버그 -> Windows -> 스레드)을 열고 각 스레드를 살펴 봅니다.

2

t.Result.Close()t 작업 완료를 기다립니다. t.ContinueWith()도 작업 완료를 기다립니다.

취소하려면 tcp와 timer의 두 가지 작업을 기다려야합니다.
비동기 TCP 구문 사용 :

await Task.WhenAny(t,Task.Delay(QueryTimeout)); 
if (!t.IsCompleted) 
    tcpClient.Close(); //Cancel task 
관련 문제