C#-解析XElement时的奇怪行为
通过将字符串解析为XElement,我观察到了一种奇怪的行为 首先,这里是我要解析的XML:C#-解析XElement时的奇怪行为,c#,parsing,xelement,C#,Parsing,Xelement,通过将字符串解析为XElement,我观察到了一种奇怪的行为 首先,这里是我要解析的XML: <return value="0"> <resultset> <meta> <column type="char(30)"></column> </meta> <datarow> <datacol>
<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()
- 您尝试在主线程中解析内存流中的数据
- 。。。然后回调实际上会将数据写入内存流
- 。。。然后,您有第二次尝试解析,它成功了,因为数据现在就在那里
\u responseBytes
写入到哪里?什么是缓冲区?还有一大堆代码我们还没有。如果你能将你的问题编辑成一个简短但完整的程序,那么会更容易帮助你。谢谢你的兴趣,请参阅编辑,我添加了更多的代码(写入响应字节的方法)。@Arnaud:我编辑了我的答案,猜测了为什么会发生这种情况。@Jon:我观察到了这种行为是的。我试过使用一个最大的缓冲区来接收数据,WaitOne在读取所有数据之前释放锁,但是我如何修复这个问题呢?有没有简单的方法或者我应该自己添加一个ManualResetEvent?谢谢回复:)
e.AsyncWaitHandle.WaitOne();