Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-解析XElement时的奇怪行为_C#_Parsing_Xelement - Fatal编程技术网

C#-解析XElement时的奇怪行为

C#-解析XElement时的奇怪行为,c#,parsing,xelement,C#,Parsing,Xelement,通过将字符串解析为XElement,我观察到了一种奇怪的行为 首先,这里是我要解析的XML: <return value="0"> <resultset> <meta> <column type="char(30)"></column> </meta> <datarow> <datacol>

通过将字符串解析为XElement,我观察到了一种奇怪的行为

首先,这里是我要解析的XML:

<return value="0">
    <resultset>
        <meta>
            <column type="char(30)"></column>
        </meta>
        <datarow>
            <datacol>
                <![CDATA[master]]>
            </datacol>
        </datarow>
    </resultset>
</return>
我在试抓块做了完全相同的事情

有时try块会引发XmlException(“根元素丢失”),但是catch块(做完全相同的事情)不会抛出它并正确解析字符串

有人能告诉我为什么吗

谢谢

[编辑]

以下是整个方法代码:

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);

        }
    } 

您没有向我们展示什么是
\u responseBytes
,但我们想到了一个建议:如果它是异步填充的(例如通过异步web请求),那么第一次尝试可能发生在数据出现之前,但在执行catch块时,数据已经到达

(显然,如果是这种情况,解决办法不是使用这种挡块,而是固定时间。)

编辑:好的,我想我可能看到了问题所在。在这里:

e.AsyncWaitHandle.WaitOne();
我怀疑它将一直等到套接字级别发生读取,但在调用回调之前。您的代码假定它等待回调完成

所以发生的事情(这仍然只是一个猜测)是:

  • 在主线程上,启动操作并等待它完成
  • 数据被读取
  • WaitOne()
    在主线程中返回,同时在线程池线程上调用回调
  • 您尝试在主线程中解析内存流中的数据
  • 。。。然后回调实际上会将数据写入内存流
  • 。。。然后,您有第二次尝试解析,它成功了,因为数据现在就在那里

请参见编辑。你是对的,所有的操作都是异步完成的,但似乎很奇怪,MemoryStream没有被填充…@Arnaud:
\u responseBytes
写入到哪里?什么是缓冲区?还有一大堆代码我们还没有。如果你能将你的问题编辑成一个简短但完整的程序,那么会更容易帮助你。谢谢你的兴趣,请参阅编辑,我添加了更多的代码(写入响应字节的方法)。@Arnaud:我编辑了我的答案,猜测了为什么会发生这种情况。@Jon:我观察到了这种行为是的。我试过使用一个最大的缓冲区来接收数据,WaitOne在读取所有数据之前释放锁,但是我如何修复这个问题呢?有没有简单的方法或者我应该自己添加一个ManualResetEvent?谢谢回复:)
e.AsyncWaitHandle.WaitOne();