0

Я создаю приложение .Net Web API, в котором следующий код вызывает вызов для моего другого приложения C# для загрузки файла, а затем сохранит его на диске. Иногда все работает нормально, и я получаю файл, но иногда код ниже не может читать поток, и я вижу закрытое исключение удаленного подключения в другом приложении.Поток от response.Content.ReadAsStreamAsync() не читается случайным образом

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

Я поставил ServicePointManager.DefaultConnectionLimit = 1000 в Global.asax.cs

В моем текущем приложении я получаю исключение на "ждут cgStream.CopyToAsync (FileStream);" когда он пытается прочитать cgStream. Исключением является «Невозможно получить доступ к закрытому потоку». с null InnerException Другое исключение для приложения: System.Web.HttpException: удаленный хост закрыл соединение. Код ошибки: 0x800703E3. на System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError (Int32 результат, булева throwOnDisconnect) в System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush() в System.Web.HttpResponse.Flush (Boolean, Boolean finalFlush асинхронном)

В среднем запрос 1 из 10 не работает с вышеуказанной ошибкой. Поскольку он случайный и не всегда не работает, очень сложно устранить проблему.

Приведенный выше код написан с помощью от: http://www.tugberkugurlu.com/archive/efficiently-streaming-large-http-responses-with-httpclient

Любая помощь в связи с этой проблемой ценится!

Благодаря

+0

_ «Удаленный хост закрыл соединение» _ - сообщение об ошибке кажется мне достаточно понятным, но ваш вопрос не так много.Почему, по вашему мнению, вы должны иметь возможность читать из потока, если соединение было закрыто? Что вы думаете о сообщении об ошибке, которое вы не понимаете? Из вашего вопроса также неясно, какой конец закрывает соединение. Несмотря на это, предоставление хорошего [mcve], который надежно воспроизводит проблему, будет иметь решающее значение для иллюстрации проблемы, о которой вы просите. –

+0

Питер, давайте не будем излишне забивать новых людей с помощью MCVE. Из его вопроса видно, что происходит, и предоставленная информация не слишком сложна. –

+0

Peter, Если закрытие соединения является основной проблемой, тогда мне нужно выяснить, что закрывает соединение случайно? 6-7 раз он срабатывает, затем внезапно эта ошибка, а затем снова работает нормально. Пожалуйста, дайте мне знать, если вам нужны какие-либо другие подробности, чтобы сделать мой вопрос более понятным для вас. –

ответ

-1

За документацию, Stream.CopyToAsync, хорошо, асинхронный. Это означает, что он не собирается блокировать вызывающего абонента (ваш метод), который будет продолжать Dispose из потока в блоке finally. Другими словами, у вас есть состояние гонки. Переключитесь на Stream.CopyTo, и вам должно быть хорошо.

+0

Привет, Крис, я попробую Stream.CopyTo вместо этого, но просто для того, чтобы сообщить вам, что я пытался использовать нижеприведенный код раньше, а позже изменил это на CopyToAsync –

+0

Даже если я удалю удаление потока из, наконец, я все еще вижу та же проблема. –

+0

Похоже, вы звоните в другую версию метода выше –

0

Я попробую 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); линии. Вы все еще думаете, что это проблема CopyToAsync? Я сомневаюсь, потому что, когда я помещаю точку прерывания, я вижу, что поток не читается, поскольку свойство Read является ложным, даже если оно не подходит к методу CopyToAsync.

Я пробовал CopyTo вместо CopyToAsync, и это не помогло. Снимок экрана:

enter image description here

2

я понял, проблема в коде: Проблема заключалась в том, что я инициализации HttpClient объект в «используя» и используя свой ответ вне сферы с использованием. Это будет уничтожать объект HttpClient, следовательно, нарушит удаленное соединение, и поэтому я не могу передать поток. Случайное поведение состояло в том, что мы не знаем, когда объект будет удален, иногда он не удаляется перед потоковой передачей, а иногда и происходит.