2010-03-16 5 views
1

Compact Framework 2.0 응용 프로그램 중 하나에서 TcpClient을 사용하고 있습니다. TCP 서버에서 정보를 받고 싶습니다.C# : Compact Framework에서 AsyncWaitHandle을 설정하는 방법?

Compact Framework는 "대형"프레임 워크의 시간 초과 메커니즘을 지원하지 않으므로 시간 초과 작업을 구현하려고합니다. 기본적으로, 나는 다음을 수행 할 :

IAsyncResult result = networkStream.BeginRead(buffer, 0, size, ..., networkStream); 
if (!result.AsyncWaitHandle.WaitOne(5000, false)) 
    // Handle timeout 


private void ReceiveFinished(IAsyncResult ar) 
{ 
    NetworkStream stream = (NetworkStream)ar.AsyncState; 
    int numBytes = stream.EndRead(ar); 

    // SIGNAL IASYNCRESULT.ASYNCWAITHANDLE HERE ... HOW?? 
} 

나는 IAsyncResult.AsyncWaitHandle에 대한 Set를 호출하고 싶습니다하지만 이러한 방법이없는 나는이에 캐스팅되는 구현 모른다.

대기 핸들을 어떻게 설정합니까? 또는 EndRead을 호출하여 자동으로 설정됩니까? 설명서는 내가 Set라고 불러야한다고 제안합니다 ...

어떤 도움을 주셔서 감사합니다!

UPDATE
EndRead를 호출 할 때 대기 핸들이 자동으로 설정되어 있는지 보인다 -하지만 문서에없는. 누군가 이것을 확인할 수 있습니까? 2

UPDATE 내 샘플 코드에 client.BeginRead를 썼다. 물론 BeginReadNetworkStream에 호출되었습니다 ...

답변

2

저는 TCP로 비동기 IO에 대한 오해가 있다고 생각합니다.

비동기 IO를 시작하려면 stream.BeginRead()를 호출하십시오.
콜백에서 스트림에서 EndRead를 호출합니다.

코드에서 볼 수 있듯이 TcpClient에서 BeginRead를 호출하지 마십시오. 앱이 WaitHandle 신호를 보내지 않습니다. IOth 레이어는 waithandle이 신호를받을 때, 즉 비동기 읽기가 발생할 때 콜백을 호출합니다.

콜백에서 더 많은 데이터를받을 가능성이있는 경우 일반적으로 스트림에서 BeginRead를 다시 호출합니다.

this answer에서 명확한 예를 볼 수 있습니다.

BeginRead/EndRead 댄스를 시작하기 전에 TcpClient에서 비동기 연결을 원할 수 있습니다. 그러면 BeginConnect를 사용할 것입니다. 그러나 그것은 단 한 번만 이루어집니다. 또는 동기 연결을 원할 수도 있습니다.이 경우 TcpClient.Connect()를 호출하면됩니다.

예제 코드 :

private class AsyncState 
    { 
     public NetworkStream ns; 
     public ManualResetEvent e; 
     public byte[] b; 
    } 

    public void Run() 
    { 
     NetworkStream networkStream = ...; 
     byte[] buffer = new byte[1024]; 

     var completedEvent = new ManualResetEvent(false); 

     networkStream.BeginRead(buffer, 0, buffer.Length, 
           AsyncRead, 
           new AsyncState 
           { 
            b = buffer, 
            ns = networkStream, 
            e = completedEvent 
           }); 

     // do other stuff here. ... 

     // finally, wait for the reading to complete 
     completedEvent.WaitOne(); 
    } 


    private void AsyncRead(IAsyncResult ar) 
    { 
     AsyncState state = ar as AsyncState; 
     int n = state.ns.EndRead(ar); 
     if (n == 0) 
     { 
      // signal completion 
      state.e.Set(); 
      return; 
     } 

     // state.buffer now contains the bytes read 
     // do something with it here... 
     // for example, dump it into a filesystem file. 

     // read again 
     state.ns.BeginRead(state.b, 0, state.b.Length, AsyncRead, state); 
    } 
+0

안녕하세요, 물론 당신이 옳아 요 - 그게 내가 뭘하는지입니다. 실제로 스트림 (위에서 업데이트 된 코드 샘플)에 대한 읽기를 시작합니다. 질문 : WaitHandle이 자동으로 신호를 받습니까? 워드 프로세서에서는 비동기 읽기가 완료 될 때까지 기다리기 위해 핸들이 설정 될 때까지 기다려야한다고 명시합니다. 나는 핸들이 EndRead를 통해 암시 적으로 설정되었다고 가정하지만, 이것을 확인할 수 있습니까? –

+1

설명서를 확인하고 "WaitOne()을 주 스레드에서 호출하고 콜백에서 Set()을 호출합니다"라고 표시된 부분을 발견했습니다. 문서가 잘못 작성되었습니다. 이 비트는 협력 스레드를 동기화하는 데 사용할 수있는 ManualResetEvent()와 같은 별도의 Waithandle을 나타냅니다.샘플 코드는 별도의 동기화 구조 ('allDone')를 보여줍니다. 불행히도 이것은 부분 코드이며 해당 변수의 초기화 또는 선언을 보여주지 않으므로 가정합니다. 그러나 그것은 IAsyncResult가 아니라는 것이 분명합니다. 최종선 : IAsyncResult에서 Set()을 호출 할 필요가 없습니다. – Cheeso

+0

그 점에 대해 감사드립니다. 이것은 제 코드에서하고있는 것과 정확히 같습니다. 나에게 잘하고있다 .-) –