[英]“stream was not readable” ArgumentException when using ReadAsStreamAsync with StreamReader
[英]Stream from response.Content.ReadAsStreamAsync() is not readable randomly
我正在开发一个.Net Web API应用程序,其中以下代码正在调用我的其他c#应用程序以下载文件,然后将其保存在磁盘上。 有时一切正常,我得到了文件,但有时以下代码无法读取流,并且可以在其他应用程序中看到远程连接关闭异常。
public async Task<string> GetFilePathAsync(TestModel model)
{
string filePath = string.Empty;
var response = await cgRequestHelper.DownloadAsync(model);
if (response.IsSuccessStatusCode)
{
filePath = await SaveCgStreamAsync(cgResponse, serviceModel.FileName);
}
return filePath;
}
public async Task<HttpResponseMessage> DownloadAsync(TestModel model)
{
if (model == null)
throw new ArgumentNullException("model");
if (string.IsNullOrEmpty(model.Url))
throw new ArgumentNullException("Url");
if (model.Headers == null)
throw new ArgumentNullException("Headers");
HttpResponseMessage response;
using (HttpClient httpClient = new HttpClient())
{
foreach (var header in model.Headers)
{
httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
}
response = await httpClient.GetAsync(model.Url, HttpCompletionOption.ResponseHeadersRead);
}
return response;
}
public async Task<string> SaveCgStreamAsync(HttpResponseMessage response, string fileName)
{
if (response == null)
throw new ArgumentNullException("response");
if (string.IsNullOrEmpty(fileName))
throw new ArgumentNullException("fileName");
var filePath = _CreateTemporaryLocation(fileName);
Stream cgStream = null;
Stream fileStream = null;
try
{
cgStream = await response.Content.ReadAsStreamAsync();
fileStream = File.Open(filePath, FileMode.Create);
await cgStream.CopyToAsync(fileStream);
}
catch(Exception e)
{
throw;
}
finally
{
if(cgStream != null)
cgStream.Dispose();
if(fileStream != null)
fileStream.Dispose();
}
return filePath;
}
我在Global.asax.cs中设置了ServicePointManager.DefaultConnectionLimit = 1000
在我当前的应用程序中,我收到“ await cgStream.CopyToAsync(fileStream);”异常。 尝试读取cgStream时显示一行。 例外是“无法访问封闭的流”。 InnerException为null另一个应用程序异常是:System.Web.HttpException:远程主机关闭了连接。 错误代码为0x800703E3。 在System.Web.HttpResponse.Flush()在System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()在System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32结果,布尔throwOnDisconnect)(布尔finalFlush,布尔异步)
平均而言,十分之一的请求失败,并出现上述错误。 由于它是随机的,并不总是失败,因此很难解决问题。
上面的代码是在以下网站的帮助下编写的: http : //www.tugberkugurlu.com/archive/ficiently-streaming-large-http-responses-with-httpclient
任何与此问题有关的帮助,我们将不胜感激!
谢谢
我在代码中发现了问题:问题是我正在“使用”中初始化HttpClient对象,并在使用范围之外使用其响应。 这将处理HttpClient对象,从而断开远程连接,这就是为什么我无法流式传输内容的原因。 随机行为是因为我们不知道对象何时会被处置,有时在流传输之前不会被处置,有时会被处置。
我将改用Stream.CopyTo
但只是为了让您知道我之前尝试了以下代码,后来将其更改为CopyToAsync
public async Task<string> GetFilePathAsync(TestModel model)
{
string filePath = string.Empty;
var response = await cgRequestHelper.DownloadAsync(model);
if (response.IsSuccessStatusCode)
{
Stream cgStream = await response.Content.ReadAsStreamAsync();
filePath = SaveCgStream(cgStream , model.FileName);
}
return filePath;
}
public string SaveCgStream(Stream cgStream, string fileName)
{
if (response == null)
throw new ArgumentNullException("response");
if (string.IsNullOrEmpty(fileName))
throw new ArgumentNullException("fileName");
const int CHUNK_SIZE = 40000;
var filePath = _CreateTemporaryLocation(fileName);
var fileStream = File.Create(filePath, CHUNK_SIZE);
int bytesRead;
var buffer = new byte[CHUNK_SIZE];
bool isReadStarted = false;
try
{
do
{
bytesRead = cgStream.Read(buffer, 0, CHUNK_SIZE);
if (bytesRead > 0)
{
isReadStarted = true;
fileStream.Write(buffer, 0, bytesRead);
}
} while (bytesRead > 0);
}
catch (Exception e)
{
throw e;
}
finally
{
fileStream.Close();
}
return filePath;
}
而且我在bytesRead = cgStream.Read(buffer, 0, CHUNK_SIZE);
得到了相同的错误bytesRead = cgStream.Read(buffer, 0, CHUNK_SIZE);
线。 您是否仍然认为这是一个CopyToAsync
问题? 我对此表示怀疑,因为当我放置一个断点时,我看到该流是不可读的,因为在甚至转到CopyToAsync
方法之前,Read属性为false。
我尝试使用CopyTo
而不是CopyToAsync
,它没有帮助。 截图:
根据文档, Stream.CopyToAsync
是异步的。 这意味着它不会阻塞调用方(您的方法),该方法将继续处理finally块中的流。 换句话说,您有比赛条件。 切换到Stream.CopyTo
,您应该Stream.CopyTo
顺利。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.