C# response.Content.ReadAsStreamAsync()中的流不可随机读取

C# response.Content.ReadAsStreamAsync()中的流不可随机读取,c#,asp.net-web-api,async-await,httpcontent,httpresponsemessage,C#,Asp.net Web Api,Async Await,Httpcontent,Httpresponsemessage,我正在制作一个.NETWebAPI应用程序,其中以下代码调用我的不同c#应用程序下载文件,然后将其保存在磁盘上。有时一切正常,我得到了文件,但有时下面的代码无法读取流,我可以在我的其他应用程序中看到远程连接关闭异常 public async Task<string> GetFilePathAsync(TestModel model) { string filePath = string.Empty; var response = await cgRequestHelp

我正在制作一个.NETWebAPI应用程序,其中以下代码调用我的不同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;            
}
公共异步任务GetFilePathAsync(TestModel模型) { string filePath=string.Empty; var response=await cgreesthelper.downloadsync(模型); if(响应。IsSuccessStatusCode) { filePath=await SaveCgStreamAsync(cgResponse,serviceModel.FileName); } 返回文件路径; } 公共异步任务下载异步(TestModel模型) { if(model==null) 抛出新的异常(“模型”); if(string.IsNullOrEmpty(model.Url)) 抛出新的ArgumentNullException(“Url”); if(model.Headers==null) 抛出新的ArgumentNullException(“头”); HttpResponseMessage响应; 使用(HttpClient HttpClient=new HttpClient()) { foreach(model.Headers中的var头) { httpClient.DefaultRequestHeaders.Add(header.Key,header.Value); } response=wait httpClient.GetAsync(model.Url,HttpCompletionOption.ResponseHeadersRead); } 返回响应; } 公共异步任务SaveCgStreamAsync(HttpResponseMessage响应,字符串文件名) { 如果(响应==null) 抛出新的异常(“响应”); if(string.IsNullOrEmpty(文件名)) 抛出新的ArgumentNullException(“文件名”); var filePath=_CreateTemporaryLocation(文件名); 流cgStream=null; Stream fileStream=null; 尝试 { cgStream=await response.Content.ReadAsStreamAsync(); fileStream=File.Open(filePath,FileMode.Create); 等待cgStream.CopyToAsync(fileStream); } 捕获(例外e) { 投掷; } 最后 { if(cgStream!=null) cgStream.Dispose(); if(fileStream!=null) Dispose(); } 返回文件路径; } 我已在Global.asax.cs中设置ServicePointManager.DefaultConnectionLimit=1000

在我当前的应用程序中,当它试图读取cgStream时,我在“await cgStream.CopyToAsync(fileStream);”行上遇到异常。异常为“无法访问关闭的流”。具有null InnerException 另一个应用程序例外是: System.Web.HttpException:远程主机已关闭连接。错误代码为0x800703E3。 在System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32结果,布尔值) 在System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()中 位于System.Web.HttpResponse.Flush(布尔finalFlush,布尔异步)

平均而言,10个请求中有1个因上述错误而失败。由于它是随机的,并且并不总是失败,因此很难对问题进行故障排除

上述代码是在以下人员的帮助下编写的:

非常感谢与此问题相关的任何帮助


谢谢

根据文档,
Stream.CopyToAsync
是异步的。这意味着它不会阻止调用方(您的方法),调用方将继续在finally块中处理流。换句话说,你有一个种族条件。切换到
Stream.CopyTo
,您就可以开始了

我将改为尝试
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;
        }
公共异步任务GetFilePathAsync(TestModel模型) { string filePath=string.Empty; var response=await cgreesthelper.downloadsync(模型); if(响应。IsSuccessStatusCode) { Stream cgStream=await response.Content.ReadAsStreamAsync(); filePath=SaveCgStream(cgStream,model.FileName); } 返回文件路径; } 公共字符串SaveCgStream(流cgStream,字符串文件名) { 如果(响应==null) 抛出新的异常(“响应”); if(string.IsNullOrEmpty(文件名)) 抛出新的ArgumentNullException(“文件名”); const int CHUNK_SIZE=40000; var filePath=_CreateTemporaryLocation(文件名); var fileStream=File.Create(文件路径、块大小); int字节读取; var buffer=新字节[块大小]; bool isReadStarted=false; 尝试 { 做 { bytesRead=cgStream.Read(缓冲区,0,块大小); 如果(字节读取>0) { isReadStarted=true; 写入(缓冲区,0,字节读取); } }而(字节读取>0); } 捕获(例外e) { 投掷e; } 最后 { fileStream.Close(); } 返回文件路径; } 我在
bytesRead=cgStream.Read(buffer,0,CHUNK\u SIZE)中得到了相同的错误行。您是否仍然认为这是一个
CopyToAsync
问题? 我对此表示怀疑,因为当我设置断点时,我可以看到流是不可读的,因为Read属性是false,甚至在转到
CopyToAsync
方法之前

我尝试了
CopyTo
而不是
CopyToAsync
,但没有效果。截图:


我在代码中找到了问题: 问题是我在“使用”中初始化HttpClient对象,并在使用范围之外使用其响应。这将处理HttpClient对象,从而中断远程连接,这就是为什么我