2016-08-23 4 views
0

У меня есть кодкак исправить код анализа предупреждения

public String makeHttpGetRequest(String url) 
     { 
      try 
      { 
       string responce = string.Empty; 
       HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
       request.AutomaticDecompression = DecompressionMethods.GZip; 


       using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
       using (Stream stream = response.GetResponseStream()) 
       using (StreamReader reader = new StreamReader(stream)) 
       { 
        responce = reader.ReadToEnd(); 
       } 
       return responce; 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("Internet Connection error" + e.Message); 
       return null; 
      } 
     } 

И я получаю предупреждение, когда я запускаю анализа кода в Visual Studio, что

CA2202 Не бросайте объекты несколько раз Object «поток 'могут быть удалены более одного раза в методе' InformationIO.makeHttpGetRequest (string) '. Для того, чтобы избежать генерирования System.ObjectDisposedException не следует вызывать Dispose больше, чем один раз на объекте .: Линии: 244 InformationIO.cs 244

линия 224 относится к линии 13 здесь закрывающую скобку перед возврата Быстродействие;

Как я могу исправить это предупреждение.

ответ

0

От MSDN

Объект StreamReader вызывает Dispose() на указанный объект потока когда StreamReader.Dispose называется.

Это означает, что StreamReader вызовет объект Dispose on Stream, и ваш оператор использования также сделает это. Альтернатива может быть:

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
    using (StreamReader reader = new StreamReader(response.GetResponseStream())) 
    { 
     responce = reader.ReadToEnd(); 
    } 
return responce; 
1

Эти две строки ссылаются на тот же stream, и будет пытаться распоряжаться его дважды:

using (Stream stream = response.GetResponseStream()) 
using (StreamReader reader = new StreamReader(stream)) 

Снимите второй using блок (из трех у вас есть), как это ненужно в этом случае.

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
{ 
    Stream stream = response.GetResponseStream()); 
    using (StreamReader reader = new StreamReader(stream)) 
    { 
     responce = reader.ReadToEnd(); 
    } 
} 

Если вы хотите быть действительно уверен поток расположен, добавьте finally блок:

Stream stream = null; 
try 
{ 
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
    { 
     stream = response.GetResponseStream()); 
     using (StreamReader reader = new StreamReader(stream)) 
     { 
      responce = reader.ReadToEnd(); 
     } 
    } 
} 
finally 
{ 
    // check if stream is not null (although it should be), and dispose of it 
    if (stream != null) 
     stream.Dispose(); 
} 
0

Чем глубже проблема здесь в том, что конструкция StreamReader неверно; он никогда не должен располагать базовый поток, потому что он не собственный.

Следующая картина довольно часто:

public class Foo: IDisposable 
{ 
    public Foo(Bar bar) {...} 
} 

public class Bar: IDisposable { ... } 

При утилизации foo, он никогда не должен распоряжаться bar автоматически для вас, потому что он не владеет bar; bar - объект, предоставленный пользователем foo; поэтому его ответственность лежит на пользователе bar.

Это, по сути, то, что происходит в вашем коде; вы правильно заботитесь о stream, но StreamReader также заботится о чем-то, что на самом деле не является его бизнесом, распоряжается stream для вас тоже.

Итак, чтобы обернуть: Ваш код верен. Из-за дефекта дизайна в StreamReader ваш правильный код создает проблему, о которой необходимо позаботиться; дублировать звонки на Dispose().

Другие ответы указывают на хорошие способы устранения проблемы, поэтому я не буду дублировать код здесь.

Смежные вопросы