sas*_*alm 5 c# asp.net-web-api
我们间歇性地The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available在WebApi端点中遇到异常。
有谁知道导致此错误的原因,或者如何以一致的方式重现该错误?目前,它发生在100,000个请求中的150个中。
XmlDeserialize()在此部分代码中引发了异常:
[HttpPost]
public async Task<IHttpActionResult> Process()
{
using (var requestStream = await Request.Content.ReadAsStreamAsync())
{
XmlSerializer serializer = new XmlSerializer(typeof(MyEntity));
// !! The below line throws the exception
MyEntity entity = serializer.Deserialize(requestStream) as MyEntity;
}
...
}
Run Code Online (Sandbox Code Playgroud)
这是完整的异常消息:
"ExceptionType": "HttpException",
"Message": "The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available.",
"StackTrace": [
"HttpBufferlessInputStream.Read;0",
"SeekableBufferedRequestStream.Read;0",
"XmlTextReaderImpl.ReadData;0",
...
Run Code Online (Sandbox Code Playgroud)
编辑:我在.NET的源代码中找到了这一点。 System.Web.txt:
HttpBufferlessInputStream_ClientDisconnected=The client is disconnected because the underlying request has been completed. There is no longer an HttpContext available.
Run Code Online (Sandbox Code Playgroud)
https://referencesource.microsoft.com/#system.web/HttpBufferlessInputStream.cs,332ecbede7a1f12a:
// We are done if the count == 0 or there is no more content
while (count > 0 && _remainingBytes != 0) {
// Do the actual read
bytesRead = wr.ReadEntityBody(buffer, offset, count);
if (bytesRead <= 0) {
if (!_context.Response.IsClientConnected) {
if (_persistEntityBody) {
SetRawContentOnce();
}
throw new HttpException(SR.GetString(SR.HttpBufferlessInputStream_ClientDisconnected));
Run Code Online (Sandbox Code Playgroud)
因此,在wr.ReadEntityBody(buffer, offset, count)返回0或负数 之后,HttpBufferlessInputStream.Read()会引发异常,并且该异常_context.Response.IsClientConnected为false。
这意味着XmlDeserialize()仍在运行时,客户端已断开连接。但是根据我对netcat的有限实验,.NET一直等到整个XML请求都已上传,甚至没有调用controller方法。因此,我们仍在反序列化时不会上载请求。
就像这里解释的那样,您应该避免捕获同步上下文并使用.ConfigureAwait(false);
[HttpPost]
public async Task<IHttpActionResult> Process()
{
using (var requestStream = await Request.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
XmlSerializer serializer = new XmlSerializer(typeof(MyEntity));
MyEntity entity = serializer.Deserialize(requestStream) as MyEntity;
}
...
}
Run Code Online (Sandbox Code Playgroud)
正如Thowk所注意到的,SynchronizationContext 已从 ASP.NET Core 中删除。
| 归档时间: |
|
| 查看次数: |
503 次 |
| 最近记录: |