Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос по Garbage Collection 
:(
    Опции темы
Renaz
Дата 2.2.2014, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.2.2014

Репутация: нет
Всего: нет



Доброго времени суток!

Довольно длительное время пишу на плюсах, привык к тому, что все время приходиться следить явно или не очень за корректным освобождением ресурсов. Посему имеется кучка непоняток с c#'овым сборщиком мусора. Например мне не понятно, корректен ли нижеследующий кусок кода, не помечает ли GC экземпляр MyTimer для удаления сразу после выхода из метода ResendCurrentPacketWithDelay? И если не помечает, то когда он это сделает? Нужно ли в TimerOnElapsed добавить  timer.Elapsed -= TimerOnElapsed; для корректной отработки сборщика мусора? По логике программы экземпляр MyTimer можно(нужно) удалить после того, как он вызовет свой колбек Elapsed. Спасибо.

Код

private void ResendCurrentPacketWithDelay(double delay) {
            var timer = new MyTimer();
            timer.Elapsed += TimerOnElapsed;
            timer.Start(delay);
        }

private void TimerOnElapsed(object sender, TimerEventArg timerEventArg) {
            var timer = (ITimer) sender;
            if (timer != null) {
                  timer.stop();
                  ResendCurrentPacket();
            }
        }

PM MAIL   Вверх
jonie
Дата 2.2.2014, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



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


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Renaz
Дата 2.2.2014, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.2.2014

Репутация: нет
Всего: нет



Цитата(jonie @ 2.2.2014,  14:57)
без знаний как реализован таймер мы не сможем дать вам ответ, ибо например в Start методе таймер может добавлять задачу, с ссылкой на себя и эта задача пока работает будет держать на него ссылку... и т.д.

Собственно MyTimer - просто обёртка над System.Timers.Timer:

Код

    public class MyTimer : ITimer
    {
        private readonly System.Timers.Timer _timer = new Timer();

        public Timer() {
            _timer.Elapsed += _timer_Elapsed;    
        }

        void _timer_Elapsed(object sender, ElapsedEventArgs e) {
            Elapsed(this, new TimerEventArg());
        }   
        public void Dispose() {
            _timer.Dispose();
        }

        public void Start(double interval) {
            _timer.Interval = interval;
            _timer.Start();
        }

        public void Stop() {
            _timer.Stop();
        }

        public event TimerEventHandler Elapsed;

        public object Clone() {
            return this.MemberwiseClone();
        }
    }


PM MAIL   Вверх
jonie
Дата 2.2.2014, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



начнем с того что у вас плохо реализован IDisposable - смотрите в MSDN как правильно.

И он помечан как ExternalThreading, а это значит что его объект надо сохранять (ссылку на него) самостоятельно - см. пример http://msdn.microsoft.com/en-us/library/sy...=vs.110%29.aspx


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Renaz
Дата 2.2.2014, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.2.2014

Репутация: нет
Всего: нет



Цитата(jonie @ 2.2.2014,  19:33)
начнем с того что у вас плохо реализован IDisposable - смотрите в MSDN как правильно.

И он помечан как ExternalThreading, а это значит что его объект надо сохранять (ссылку на него) самостоятельно - см. пример http://msdn.microsoft.com/en-us/library/sy...=vs.110%29.aspx

Спасибо. Читал МСДН, мало понял. Трюк с предотвращением повторного вызова кода понятен, не понятна разница между явным вызовом Dispose() программистом, и автоматическим вызовом деструктора(?) сборщиком? По идее одна задача должна быть у них - освободить какие-либо занятые ресурсы? И еще вопрос по GC.KeepAlive - в msdn написано, что 
Цитата

The KeepAlive method performs no operation and produces no side effects other than extending the lifetime of the object passed in as a parameter.
 На сколько этот метод увеличивает livetime объекта? Ниже исправленный код (возможно до сих пор не корректный), написанный по образу и подобию мсдн'овского, но всё равно логика не понятна.

Код

        private void ResendCurrentPacketWithDelay(double delay) {
            var timer = new MyTimer;
            GC.KeepAlive(timer);
            timer.Elapsed += TimerOnElapsed;
            timer.Start(delay);
        }

        private void TimerOnElapsed(object sender, TimerEventArg timerEventArg) {
            var timer = (ITimer) sender;
            if (timer == null) return;
            ResendCurrentPacket();
            timer.Dispose();
        }


и часть кода из MyTimer:
Код

        public MyTimer() {
            _disposed = false;
            _timer.Elapsed += _timer_Elapsed;
        }

        ~MyTimer() {
            Dispose(false);
        }

        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing) {
            if (_disposed) return;
            if (disposing) {
                _timer.Elapsed -= _timer_Elapsed;
                _timer.Dispose();    
            }
            _timer = null;    
            _disposed = true;
        }

PM MAIL   Вверх
jonie
Дата 3.2.2014, 08:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Цитата(Renaz @  2.2.2014,  21:51 Найти цитируемый пост)
возможно до сих пор не корректный

не возможно, а так и есть.. GC.KeepAlive делаете, но не отзываете своё требование..
вообще сохраните экземпляр таймера и не парьте мозг, GC.KeepAlive не для этого создан.


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Renaz
Дата 3.2.2014, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 2.2.2014

Репутация: нет
Всего: нет



Цитата(jonie @ 3.2.2014,  08:46)
Цитата(Renaz @  2.2.2014,  21:51 Найти цитируемый пост)
возможно до сих пор не корректный

не возможно, а так и есть.. GC.KeepAlive делаете, но не отзываете своё требование..
вообще сохраните экземпляр таймера и не парьте мозг, GC.KeepAlive не для этого создан.

Ок, понял. Не посоветуете какую-нибудь литературу по GC в .NET почитать? А резюмируя по первому вопросу - объект помечается для удаления если на него самого у никого нет ссылок и он сам не имеет ссылок на активные объекты?
PM MAIL   Вверх
jonie
Дата 3.2.2014, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Алгоритм действия GC примерно такой (сииильно упрощенно): все объекты помечаются как удаленные, затем GC проходит по графу и оживляет те, на которые есть ссылки из графа, после этого "удаляет" оставшееся.
)
Про GC читать книжку Under the Hood of .NET Memory Management (Chris Farrell and Nick Harrison), ну и рихтера, конечно перед этим всем...


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Certain
Дата 3.2.2014, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 235
Регистрация: 18.6.2008
Где: Moscow

Репутация: нет
Всего: 4



Хотелось бы добавить к вышесказанному:
1. Советую почитать отличную статью (помимо главы Джефри Рихтера про GC) про эталон освобождения ресурсов Dispose pattern, особенно про способы реализации данного паттерна для объектов, содержащих управляемые и/или неуправляемые ресурсы.
В Вашем случае объект является обёрткой над управляемым ресурсом Timer, такой реализации интерфейса IDisposable будет достаточно (реализация финализатора в данном случае будет лишней, нет необходимости)
Код

 public void Dispose() {
            _timer.Dispose();
        }

2. 
Код

private void TimerOnElapsed(object sender, TimerEventArg timerEventArg) {
            var timer = (ITimer) sender;
            if (timer == null) return;
            ResendCurrentPacket();
            timer.Dispose();
        }


timer.Dispose(); лучше вызвать до метода ResendCurrentPacket();.
Если требуется много времени для работы метода ResendCurrentPacket();, таймер может сработать ещё раз до завершения ResendCurrentPacket();.
--------------------
Работа программиста и шамана имеет много общего - оба боpмочyт непонятные слова, совершают непонятные действия и не могут объяснить, как оно работает.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0521 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.