2011-01-14 15 views
1

文字列をXElementに解析して異常な動作を観察しました。今すぐコードC# - XElementの解析中に異常な動作が発生しました

<return value="0"> 
    <resultset> 
     <meta> 
      <column type="char(30)"></column> 
     </meta> 
     <datarow> 
      <datacol> 
       <![CDATA[master]]> 
      </datacol> 
     </datarow> 
    </resultset> 
</return> 

::私はtryおよびcatchブロックでまったく同じことを行う

  try 
      { 
       xmlResult = XElement.Parse(
        _UTF8Encoder.GetString(_responseBytes.GetBuffer(), 0, (int)_responseBytes.Length), 
        LoadOptions.PreserveWhitespace); 
      } 
      catch 
      { 
       xmlResult = XElement.Parse(
        _UTF8Encoder.GetString(_responseBytes.GetBuffer(), 0, (int)_responseBytes.Length), 
        LoadOptions.PreserveWhitespace); 
      } 

まず、ここで私が解析したいXMLです。

いつかtryブロックはXmlException( "ルート要素がありません")を発生させますが、まったく同じことをしているcatchブロックはそれをスローして正しく解析しません。

誰かが私にその理由を教えてもらえますか?

ありがとうございます!

[EDIT]ここ

は、全体メソッドのコードです:

private TcpClient _client; 
private NetworkStream _clientStream; 
private MemoryStream _responseBytes; 
private readonly UTF8Encoding _UTF8Encoder = new UTF8Encoding(); 
private const int BUFFER_SIZE = 1024; 

    private XElement Receive() 
    { 
     byte[] buffer = new byte[BUFFER_SIZE]; 

     XElement xmlResult; 
     Encoding serverEncoding = this.Task.Server.Encoding; 

     // Reading result 
     while (true) 
     { 
      _responseBytes = new MemoryStream(); 

      try 
      { 
       IAsyncResult e = _clientStream.BeginRead(buffer, 
        0,            // Begin 
        BUFFER_SIZE,         // Length 
        new AsyncCallback(OnBeginRead),     // Callback used 
        new SocketAsyncState(_clientStream, buffer)); // Passing buffer to callback 

       e.AsyncWaitHandle.WaitOne(); // Wait until data are in pipe 

       if (((SocketAsyncState)e.AsyncState).HasError) 
       { 
        throw new ObjectDisposedException(); 
       } 

       // Try to convert to a XElement, if fail, redo all process. 
       _responseBytes.Position = 0; 

       try 
       { 
        xmlResult = XElement.Parse(
         _UTF8Encoder.GetString(_responseBytes.GetBuffer(), 0, (int)_responseBytes.Length), 
         LoadOptions.PreserveWhitespace); 
       } 
       catch 
       { 
        xmlResult = XElement.Parse(
         _UTF8Encoder.GetString(_responseBytes.GetBuffer(), 0, (int)_responseBytes.Length), 
         LoadOptions.PreserveWhitespace); 
       } 

       // Result 100% retrieved : quit loop 
       break; 
      } 
      catch (Exception ex) 
      { 

       if (ex is ObjectDisposedException 
        || ex is XmlException) 
       { 
        while (!IsConnected) { Wait(); } // Wait that the network comes back 
        SendSyn();       // Relaunch process 
       } 
      } 
     } 

     // Result 100% retrieved : send ACK to Socket 
     SendAck(); 

     return xmlResult; 
    } 

    private void OnBeginRead(IAsyncResult ar) 
    { 
     SocketAsyncState state = ar.AsyncState as SocketAsyncState; 
     byte[] nextBuffer = new byte[BUFFER_SIZE]; 
     int numberOfBytesReaded; 
     Encoding serverEncoding = this.Task.Server.Encoding; 

     try 
     { 
      numberOfBytesReaded = state.Stream.EndRead(ar); 
     } 
     catch(Exception) 
     { 
      ((SocketAsyncState)ar.AsyncState).HasError = true; 
      // Quit 
      return; 
     } 

     // While data are available, read next buffer (recursive call to this method) 
     if (state.Stream.DataAvailable && state.Stream.CanRead) 
     { 
      state.Stream.BeginRead(nextBuffer, 
       0, 
       BUFFER_SIZE, 
       new AsyncCallback(OnBeginRead), 
       new SocketAsyncState(state.Stream, nextBuffer)); 
     } 

     // Default C# strings are in UTF-8, so convert stream only if needed 
     if (serverEncoding.CodePage != _UTF8Encoder.CodePage) 
     { 
      byte[] buffer = Encoding.Convert(serverEncoding, 
       _UTF8Encoder, 
       state.Data.TakeWhile((b) => b != '\0').ToArray()); 

      _responseBytes.Write(buffer, 0, buffer.Length); 
     } 
     else 
     { 
      _responseBytes.Write(state.Data, 0, numberOfBytesReaded); 

     } 
    } 

答えて

3

あなたが何であるか_responseBytes私たちに示していないが、1つの提案を念頭にスプリング:例えば経て(それが非同期に作成されていた場合データが存在する前に最初の試行が発生する可能性がありますが、キャッチブロックが実行される時点までにデータが到着している可能性があります。

は、(このような場合には明らかに、解決策はない catchブロックのこの種を使用するが、タイミングを修正することです。)

EDIT:さて、私はおそらく問題を参照してくださいと思います。それはここにある:

e.AsyncWaitHandle.WaitOne(); 

私はコールバックが呼び出される前に、読み取りがソケットレベルで発生しましたが、するまで待機しますと思われます。あなたのコードは、コールバックがで完了するまで待つと仮定しています。

だから、何が起こっているか(これはまだ単なる推測ですが)である:あなたのメインスレッド上で

  • 、あなたが操作をキックオフし、それが
  • を完了するのを待つデータが
  • を読まれますWaitOne()がメインスレッドに戻り、同時にスレッドプールスレッドでコールバックが呼び出されます
  • メインスレッドのメモリストリームからデータを解析しようとしています...
  • ... D その後、コールバックは、実際にメモリストリーム
  • にデータを書き込み...とその後、あなたはデータが今あるので、成功する構文解析で2回目の試行を、持っている
+0

編集を参照してください。あなたは正しいのですが、非同期的に行われますが、MemoryStreamにデータが設定されていないことは非常に奇妙なようです... –

+0

@Arnaud: '_responseBytes'はどこに書き込まれますか? 'buffer'とは何ですか?私たちがまだ持っていないコードがたくさんあります。あなたが短いが完全な*プログラムにあなたの質問を編集できるなら、あなたを助けるほうがはるかに簡単です。 –

+0

おかげで、面白いです、編集を参照してください、私は_responseBytesが書かれている方法)より多くのコードを追加しました。 –

関連する問題