2011-10-30 5 views
3

私はネットワークストリームとコールバック関数newDataRecievedCallbackを読み込んでいるlisten()関数を持っています。これは非同期の読みですか?

私は非同期あるBeginReadメソッドを呼び出しますが、私は再びコールバック関数内で同じメソッドを呼び出します。それは同期ロジックですか?

これには別の方法がありますか?

private void listen() 
    { 
     networkStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(newDataRecievedCallback), null); 
    } 

    private void newDataRecievedCallback(IAsyncResult rst) 
    { 
     try 
     { 
      int recievedDataSize = tcpClient.Client.Receive(buffer); 
      recievedData = convertToString(buffer, incomeDataSize); 

      //End Read 
      networkStream.EndRead(rst); 
      cleanBuffer(); 
      parseXMLData(recievedData); 

      //Hier I call the same async method 
      networkStream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(newDataRecievedCallback), null); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 

答えて

3

networkStream.BeginReadへの電話がブロックされないため、まだ非同期です。呼び出しを行い、関数を終了します。はい、それは再び呼び出されますが、まだ非同期的に呼び出されます。

別の方法がありますか?はい、数百の方法。あなたのコードは悪くありません。あなたの非同期ハンドラがデータを処理するだけでなく、独自の管理を実行しているという点でちょっとしたことがあります。より洗練された方法は、あなたのnewDataRecievedCallbackがデリゲートを介して通知し、処理のためにデータを渡す何らかのコントローラを持つことです。コントローラはまた、次の非同期プロセスを開始する責任があります。別のコントローラは、より多くの非同期呼び出しをブロックすることなく、処理のために受信したデータを渡すこともできます。

+0

「BeginRead」は時には**同期的に**完了します。彼のコードはスタックオーバーフローの影響を受けやすい。 –

+0

@Paul Sasik例が非常にいい – Racooon

4

常にBeginRead完了した場合、非同期その後、まだ非同期になりますコールバックで再びそれを呼び出します。

BeginReadが時々同期して(チェックIAsyncResult.CompletedSynchronously)完了することがあります。そのため、不運になるとコードがスタックオーバーフローの影響を受けやすくなります。たとえば、これは1つのスレッドで発生する可能性があります。newDataRecievedCallback - >BeginRead - >newDataRecievedCallback - >BeginReadなどです。

BeginReadを使用する適切な方法は、以下のようなパターンを使用することです(これはNutshellのC#4.0のcode snippetです)。本質的には、メソッドが同期的に完了したかどうかを常にチェックしてから、適切に処理する必要があります。

void Read()   // Read in a nonblocking fashion. 
{ 
    while (true) 
    { 
    IAsyncResult r = _stream.BeginRead 
    (_data, _bytesRead, _data.Length - _bytesRead, ReadCallback, null); 

    // This will nearly always return in the next line: 
    if (!r.CompletedSynchronously) return; // Handled by callback 
    if (!EndRead (r)) break; 
    } 
    Write(); 
} 

void ReadCallback (IAsyncResult r) 
{ 
    try 
    { 
    if (r.CompletedSynchronously) return; 
    if (EndRead (r)) 
    { 
     Read();  // More data to read! 
     return; 
    } 
    Write(); 
    } 
    catch (Exception ex) { ProcessException (ex); } 
} 

bool EndRead (IAsyncResult r) // Returns false if there’s no more data 
{ 
    int chunkSize = _stream.EndRead (r); 
    _bytesRead += chunkSize; 
    return chunkSize > 0 && _bytesRead < _data.Length; // More to read 
} 
関連する問題