оптимізація додатків

Однак іноді буває бажано зберегти невидимою рядок, пов'язану з об'єктом, не заважаючи при цьому збирачеві сміття видалити об'єкт з пам'яті. Коли збирач сміття видалить об'єкт, рядок виявиться не пов'язаної ні з яким об'єктом, і ми зможемо визначити це. Якщо збирач сміття ще не торкався до об'єкта, за допомогою цього рядка ми зможемо відновити сильну посилання на об'єкт і використовувати його знову.

Це може стати в нагоді в різних ситуаціях, найбільш типові з яких перераховані нижче:

Користування зовнішніми послугами без збереження об'єкта. Такі послуга, як таймери і події, можуть надаватися об'єктам без збереження посилань на них, що може сприяти усуненню типових причин витоку пам'яті.

Автоматичне управління стратегією кешування або підтримки пулу об'єктів. Кеш може зберігати слабкі посилання на недавно використовувалися об'єкти, не заважаючи їх утилізації; пул може бути розділений на дві частини - основну, мінімального розміру, що зберігає сильні посилання, і додаткову, яка містить слабкі посилання.

Утримання великих об'єктів в надії, що вони не будуть утилізовані. Додаток може зберігати слабку посилання на великий об'єкт, для створення і ініціалізації якого потрібно багато часу. Якщо об'єкт виявиться знищений складальником сміття, додаток зможе повторно створити його; в іншому випадку його можна використовувати повторно.

Майте на увазі, що єдиним безпечним способом отримання суворої посилання на об'єкт слабкою посилання є властивість Target. Навіть якщо властивість IsAlive поверне true, є ймовірність, що відразу після цього об'єкт буде утилізовано. Щоб уникнути стану гонки, спочатку слід використовувати властивість Target, привласнити повертається їм значення сильної посиланням (локальної змінної, полю і так далі) і потім порівняти отримане значення на рівність null. Властивість IsAlive слід використовувати, лише коли необхідно визначити факт знищення об'єкта; наприклад, щоб видалити слабку посилання з кеша.

Нижче демонструється чорнова версія реалізації подій на основі слабких посилань (як показано на малюнку). Сама подія не може використовувати механізм делегатів .NET безпосередньо, тому що делегат зберігає сильну посилання на свою мету і це є заважає обставиною. Однак, можна зберігати мета делегата (у вигляді слабкої посилання). Такий підхід дозволяє позбутися від однієї з найбільш типових причин витоків пам'яті в .NET, коли через забудькуватість події продовжують залишатися зареєстрованими!

оптимізація додатків

Генератор подій зберігає слабкі посилання на всіх передплатників. Якщо передплатник виявиться недосяжний для додатка, генератор подій зможе визначити це по появі значення null в слабкій посиланням.

Дескриптори збирача сміття

зберігати звичайну (сильну) посилання на об'єкт, перешкоджаючи його утилізації; представлено значенням GCHandleType.Normal;

зберігати коротку слабку посилання на об'єкт; представлено значенням GCHandleType.Weak;

зберігати довгу слабку посилання на об'єкт; представлено значенням GCHandleType.WeakTrackResurrection;

На практиці дескриптори збирача GC рідко використовуються безпосередньо, але вони часто беруть участь в результатах профілювання, як ще один тип коренів, що дозволяють утримувати керовані об'єкти.

Схожі статті