Здравствуйте, FlyDN, Вы писали:
FDN>В следующем коде "Finalizer" мы не увидим никогда, а почему?
Ответ на данный вопрос скрыт внути класса Timer. Если, скажем, сделать ему Dispose, то наблюдать вызов финалайзера мы начинаем в ождидаемом месте.
А дело все в том, что все созданные таймеры регистрируются в VM. Код из Рефлектора:
public Timer(TimerCallback callback)
{
int num1 = -1;
int num2 = -1;
StackCrawlMark mark1 = StackCrawlMark.LookForMyCaller;
this.TimerSetup(callback, this, (uint) num1, (uint) num2, ref mark1);
}
Далее:
private void TimerSetup(TimerCallback callback, object state, uint dueTime, uint period, ref StackCrawlMark stackMark)
{
this.timerBase = new TimerBase();
this.timerBase.AddTimer(callback, state, dueTime, period, ref stackMark);
}
И наконец
internal void AddTimer(TimerCallback callback, object state, uint dueTime, uint period, ref StackCrawlMark stackMark)
{
if (callback == null)
{
throw new ArgumentNullException("TimerCallback");
}
_TimerCallback callback1 = new _TimerCallback(callback, state, stackMark);
state = callback1;
this.AddTimerNative(state, dueTime, period, ref stackMark);
this.timerDeleted = 0;
}
Здесь
[MethodImpl(MethodImplOptions.InternalCall)]
private extern void AddTimerNative(object state, uint dueTime, uint period, ref StackCrawlMark stackMark);
так что для того, чтобы отследить вызов дальше, придется копаться в C++-коде виртуальной машины (например, в Роторе).
Итак, глобальная таблица косвенно держит делегат, который держит экземпляр Test.
Мораль: не пренебрегайте вызовом Dispose. Иначе некоторе финалайзеры у вас вызовутся лишь при app domain shutdown