объяснить, почему объект имеет время жизни вне области - PullRequest
2 голосов
/ 19 июля 2010

Я написал класс следующим образом.Я написал его, принимая во внимание, что он в основном предназначен для использования в Интернете (то есть будет использоваться на страницах aspx).

public class TestHelper
{    
    public TestHelper()
    {
        HttpContext ctxt = HttpContext.Current;
        IHttpHandler RequestHandler = ctxt.Handler;
        Page CurrentPage;
        CurrentPage = (Page)RequestHandler;
        CurrentPage.Unload += new EventHandler(CurrentPage_Unload); 
        Debug.Print("Open all connection here...");
    }

    void CurrentPage_Unload(object sender, EventArgs e)
    {
        Debug.Print("Close all connection here...");
    }
}

И я написал код своей страницы aspx так:1004 *

public partial class _Default : System.Web.UI.Page 
{    
    protected void Page_Load(object sender, EventArgs e)
    {
        TestHelper helper = new TestHelper();
        helper = null;
    }

}

Несмотря на назначение помощника 'null', я обнаружил, что CurrentPage_Unload() выполняется.Почему это поведение так?Как обычно называется это поведение?

Причина, по которой я написал урок в этом стиле, заключалась в том, что я думал, что лучше всего смогу управлять своими соединениями БД центральным образом в классе.Обычно люди вызывают методы для объекта, такие как helper.IsValid(), за которым следует helper.ProfileExists() в коде aspx.Каждый из этих методов будет иметь свои собственные объекты подключения к базе данных (IDbConnection) и соответствующие им Open() & Close() вызовы для открытия / закрытия подключения к базе данных.Я просто чувствовал, что мы должны делать это только один раз в коде.Поэтому я использовал конструктор, чтобы открыть соединения БД, и событие unload объекта Page, чтобы закрыть объекты соединения.Есть ли какие-либо подводные камни для написания классов таким образом?

Ответы [ 3 ]

4 голосов
/ 19 июля 2010

Что происходит, вы присоединяете делегата к событию Unload страницы. Даже после того, как для вашей переменной задано значение NULL, ваша страница все еще существует и все еще имеет событие Unload, которое по-прежнему содержит ссылку на делегата, которого вы добавили в нее.

Для удаления делегата необходимо использовать синтаксис -=.

CurrentPage.Unload -= new EventHandler(CurrentPage_Unload); 
2 голосов
/ 19 июля 2010

Присвоение null переменной не завершает ее фактическое время жизни. Поскольку .NET использует недетерминированную систему сбора мусора (где объекты периодически очищаются на основе нескольких критериев, а не как только они выпадают из области действия), вы не можете полагаться на объект когда-либо , собираемый ранее процесс, который его создал, заканчивается.

Кроме того, поскольку вы присоединяете обработчик события (имеется в виду делегат, который включает ссылку на ваш недавно созданный экземпляр) к другому объекту, вы продлеваете время жизни viable вашего объекта как Что ж. Пока этот обработчик событий присоединен, ваш объект не может быть собран до тех пор, пока объект, к которому он присоединен, не имеет права.

0 голосов
/ 19 июля 2010

Вы должны подумать о том, что происходит, когда вы выполняете строку

helper = null;

У вас просто есть ссылка на объект. Когда вы присваиваете этому объекту значение null, вы просто устанавливаете ссылку на null. Ничего не случилось с объектом. Рассмотрим следующий код:

var first = new object();
second = first;

first = null;

Секунда теперь будет нулевой? Вы можете рассматривать ссылку как просто число - это просто адрес объекта в памяти.

Сборщик мусора .NET просто просматривает объекты и проверяет, есть ли ссылки на этот объект. Если нет, он удалит этот объект.

...