Как предотвратить сбой (утечку памяти), используя статические методы? - PullRequest
1 голос
/ 24 февраля 2012

Я использую ASP.NET 4.0.

За последние несколько недель мало кто жалуется, что приложение начинает работать со сбоями. GridView неожиданно начинает показывать содержимое элемента управления DropDown, к которому тот же пользователь или другой параллельный пользователь могли получить доступ в любой момент времени в этот день. Аналогично, элементы управления DropDown могут заполняться RowID любого старого набора результатов вместо фактических элементов.

Мне попалась статья: Пользователи видят данные других пользователей в ASP.NET , где автор обсуждает статические объекты, ответственные за поведение утечки памяти.

Это напоминает мне класс в моем проекте, который Static и содержит public static методы. Этот класс содержит методы для заполнения DropDown, возврата DataSet для ввода запроса или возврата скалярного объекта на основе ввода запроса.

Ниже приведена выдержка из этого класса:

public static class reuse
{
    public static void FillDropDownList(string Query, DropDownList DropDownName, string ConnectionStringParameter)
    {
        SqlDataReader dr;

        try
        {
            dbConnection.OpenConnection(ConnectionStringParameter);

            //Check whether the Drop Down has existing items. If YES, empty it.
            if (DropDownName.Items.Count > 0)
                DropDownName.Items.Clear();

            SqlCommand cmd = new SqlCommand(Query,dbConnection.cn);
            dr = cmd.ExecuteReader();

            DropDownName.Items.Add("-- Select --");
            DropDownName.Items.Add("All");
            while (dr.Read())
                DropDownName.Items.Add(dr[0].ToString());

            dr.Close();
        }
        catch (Exception ex)
        {
            rpkCustomErrorHandler.GetScript(HttpContext.Current.Response,ex.Message.ToString());
        }
        dbConnection.CloseConnection();
    }
}

Я хочу знать, является ли это причиной неисправности, о которой я говорил выше. Если да, есть ли способ утилизировать статические методы после завершения задачи метода. Нужно ли менять класс со статического на простой класс по умолчанию?

Отредактировано

У меня есть другой класс, который также является статическим и используется вышеуказанным классом:

public static class dbConnection
{
    public static SqlConnection cn = new SqlConnection();

    public static void OpenConnection()
    {
        try
        {
            cn.ConnectionString = ConfigurationManager.ConnectionStrings["cnWebTwDrill"].ToString();

            if (cn.State == ConnectionState.Closed)
                cn.Open();
        }
        catch (Exception)
        {
            throw;              
        }
    }
}

Должен ли я удалить «Static» из класса подключения и сделать вызов этому классу, используя каждый раз уникальный экземпляр?

Ответы [ 3 ]

3 голосов
/ 24 февраля 2012

Код, который вы нам показали, является примером неправильного использования статического класса / метода.Вы помещаете в статический метод или класс вещи, которые просто помещаются в объект и которые НЕ ТРЕБУЮТ состояния.

Функциональность, которую вы там используете, должна быть разделена между бизнес-уровнем (который будет извлекать данные) и UI / COntroller (в данном случае Page), где вы назначаете данные серверному элементу управления.Все эти операции являются специфическими для запроса, для этого нет оснований использовать статический метод.Это просто признак (плохого) процедурного программирования.А при работе с БД (или одноразовыми объектами) вы должны использовать оператор , используя .Примерно так:

using(var conex=GetConnection())
{
   try
   {
     conex.Open(); 
     //do stuff

    var cmd= new SqlCommand();//cfg command
    using (var rd= cmd.ExecuteReader())   
      {
           //do read
      }
   }
   catch(Exception ex)
    {
       //handle exception
    }
}

Оператор , использующий , автоматически вызывает Dispose в конце блока.Это в основном ярлык для

try {}
finally{ //dispose }.
1 голос
/ 24 февраля 2012

Я сомневаюсь, что ошибка, которую вы видите, вызвана утечкой памяти или невозможностью избавиться от статических объектов.

Однако, чтобы ответить на ваш вопрос: единственный способ освободить память, хранимую статическими объектами, - установить для связанных статических ссылок значение null. После этого они не будут доступны, и GC позаботится обо всем остальном.

Две вещи, которые могут помочь с реальной проблемой:

  1. Неправильные стратегии кэширования могут вызвать непреднамеренный обмен данными (на уровне HTTP или с кэшем объектов ASP.NET, кэшированием вывода и т. Д.)
  2. Обязательно используйте блокировку вокруг всех ссылок на статические объекты, которые могут быть разделены между потоками, где один поток может записывать объект, а другой читает его.

Кстати, статический метод в OP не использует статические объекты; все, к чему он прикасается, представляется аргументом. Только статические методы не выделяют и не хранят ссылки на память.

Обновление:

Попытка совместного использования соединения с одной БД между запросами страниц является ошибкой и почти наверняка приведет к неопределенному поведению (например, одна страница может выполнить запрос, а другая страница читает ответ). Соединения с БД уже объединены во время выполнения; вам не нужно оптимизировать эту часть самостоятельно. Каждый запрос к странице должен не только использовать новый SqlConnection, но также должен вызывать Dispose() для объекта соединения впоследствии, чтобы незамедлительно освободить его обратно в пул.

1 голос
/ 24 февраля 2012

Это не вопрос утечки или утилизации, это вопрос использования статических объектов с состоянием. Эта функция является статической, но она не требует полного состояния. Весь контекст операции присутствует в вызове, так как все объекты этого класса, которые не являются параметрами, будут очищены автоматически. Однако, если вы определили некоторый тип статических данных, это значение получат все пользователи в одном домене приложения. Это значит, что вы должны быть осторожны всякий раз, когда используете статические данные, поскольку их сложно протестировать, заменить и они очень сложны в многопоточных ситуациях.

...