| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > .NET для новичков > Вопрос по Garbage Collection |
| Автор: Renaz 2.2.2014, 14:55 | ||
| Доброго времени суток! Довольно длительное время пишу на плюсах, привык к тому, что все время приходиться следить явно или не очень за корректным освобождением ресурсов. Посему имеется кучка непоняток с c#'овым сборщиком мусора. Например мне не понятно, корректен ли нижеследующий кусок кода, не помечает ли GC экземпляр MyTimer для удаления сразу после выхода из метода ResendCurrentPacketWithDelay? И если не помечает, то когда он это сделает? Нужно ли в TimerOnElapsed добавить timer.Elapsed -= TimerOnElapsed; для корректной отработки сборщика мусора? По логике программы экземпляр MyTimer можно(нужно) удалить после того, как он вызовет свой колбек Elapsed. Спасибо.
|
| Автор: jonie 2.2.2014, 14:57 |
| без знаний как реализован таймер мы не сможем дать вам ответ, ибо например в Start методе таймер может добавлять задачу, с ссылкой на себя и эта задача пока работает будет держать на него ссылку... и т.д. |
| Автор: Renaz 2.2.2014, 15:08 | ||||
Собственно MyTimer - просто обёртка над System.Timers.Timer:
|
| Автор: jonie 2.2.2014, 19:33 |
| начнем с того что у вас плохо реализован IDisposable - смотрите в MSDN как правильно. И он помечан как ExternalThreading, а это значит что его объект надо сохранять (ссылку на него) самостоятельно - см. пример http://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.110%29.aspx |
| Автор: Renaz 2.2.2014, 20:51 | ||||||||
Спасибо. Читал МСДН, мало понял. Трюк с предотвращением повторного вызова кода понятен, не понятна разница между явным вызовом Dispose() программистом, и автоматическим вызовом деструктора(?) сборщиком? По идее одна задача должна быть у них - освободить какие-либо занятые ресурсы? И еще вопрос по GC.KeepAlive - в msdn написано, что
и часть кода из MyTimer:
|
| Автор: jonie 3.2.2014, 08:46 |
не возможно, а так и есть.. GC.KeepAlive делаете, но не отзываете своё требование.. вообще сохраните экземпляр таймера и не парьте мозг, GC.KeepAlive не для этого создан. |
| Автор: Renaz 3.2.2014, 09:11 | ||
Ок, понял. Не посоветуете какую-нибудь литературу по GC в .NET почитать? А резюмируя по первому вопросу - объект помечается для удаления если на него самого у никого нет ссылок и он сам не имеет ссылок на активные объекты? |
| Автор: jonie 3.2.2014, 10:16 |
| Алгоритм действия GC примерно такой (сииильно упрощенно): все объекты помечаются как удаленные, затем GC проходит по графу и оживляет те, на которые есть ссылки из графа, после этого "удаляет" оставшееся. ) Про GC читать книжку Under the Hood of .NET Memory Management (Chris Farrell and Nick Harrison), ну и рихтера, конечно перед этим всем... |
| Автор: Certain 3.2.2014, 10:57 | ||||
| Хотелось бы добавить к вышесказанному: 1. Советую почитать отличную статью (помимо главы Джефри Рихтера про GC) про эталон освобождения ресурсов http://habrahabr.ru/post/129283/, особенно про способы реализации данного паттерна для объектов, содержащих управляемые и/или неуправляемые ресурсы. В Вашем случае объект является обёрткой над управляемым ресурсом Timer, такой реализации интерфейса IDisposable будет достаточно (реализация финализатора в данном случае будет лишней, нет необходимости)
2.
timer.Dispose(); лучше вызвать до метода ResendCurrentPacket();. Если требуется много времени для работы метода ResendCurrentPacket();, таймер может сработать ещё раз до завершения ResendCurrentPacket();. |