Оновлення (1 грудня 2009 р.):
Я хотів би змінити цю відповідь і визнати, що початкова відповідь була помилковою.
Оригінальний аналіз дійсно застосовується до об'єктів, які потребують доопрацювання - і точка, згідно з якою практики не повинні бути прийняті на поверхні без точного, глибокого розуміння, все ще існує.
Однак виявляється, що DataSets, DataViews, DataTables пригнічують доопрацювання у своїх конструкторах - саме тому виклик Dispose () на них явно нічого не робить.
Імовірно, це відбувається тому, що вони не мають некерованих ресурсів; тому, незважаючи на те, що MarshalByValueComponent допускає керування некерованими ресурсами, ці конкретні реалізації не потребують і тому можуть відмовитися від доопрацювання.
(Саме автори .NET піклуються про придушення доопрацювання тих самих типів, які зазвичай займають найбільше пам’яті, говорить про важливість цієї практики в цілому для доопрацьованих типів.)
Незважаючи на те, що ці деталі ще недостатньо задокументовані з моменту створення .NET Framework (майже 8 років тому), досить дивно (що ви по суті залишаєтесь власним пристроям, щоб просіяти хоч суперечливий, неоднозначний матеріал, щоб скласти шматки разом часом неприємно, але це дає більш повне розуміння рамок, на які ми покладаємось щодня).
Після багато прочитаного, ось моє розуміння:
Якщо об'єкт потребує доопрацювання, він може займати пам'ять довше, ніж потрібно - ось чому: а) будь-який тип, який визначає деструктор (або успадковує тип, який визначає деструктор), вважається остаточним; б) при виділенні (до запуску конструктора) вказівник розміщується на черзі завершення; c) Об'єкт, що підлягає завершенню, вимагає відновити 2 колекції (замість стандартних 1); d) Придушення завершення не видаляє об'єкт із черги завершення (як повідомляється! FinalizeQueue в SOS) Ця команда вводить в оману; Знання, які об’єкти знаходяться у черзі на завершення (саме по собі), не є корисним; Знання, які об’єкти знаходяться в черзі на завершення та все ще потребують доопрацювання, було б корисним (чи є команда для цього?)
Придушення фіналізації дещо відключається у заголовку об’єкта, вказуючи на час виконання, що йому не потрібно мати виклик його Finalizer (не потрібно переміщувати чергу очередей); Він залишається у черзі на завершення (і продовжує повідомляти! FinalizeQueue в SOS)
Усі класи DataTable, DataSet, DataView вкорінені в MarshalByValueComponent, об'єкт, що може завершитися, який може (потенційно) обробляти некеровані ресурси
- Оскільки DataTable, DataSet, DataView не вводять керовані ресурси, вони пригнічують доопрацювання у своїх конструкторах
- Хоча це незвичайний зразок, він звільняє абонента від турботи про виклик утилізувати після використання
- Це, а також той факт, що DataTables потенційно можна ділитись між різними наборами даних, ймовірно, чому DataSets не піклується про розпорядження дочірніми DataTables
- Це також означає, що ці об'єкти з'являться під! FinalizeQueue в SOS
- Однак ці об’єкти все-таки мають бути повернені після єдиної колекції, як і їхні аналоги, що не завершуються
4 (нові посилання):
Оригінальний відповідь:
На це є багато оманливих і взагалі дуже поганих відповідей - кожен, хто приземлився тут, повинен ігнорувати шум і уважно читати посилання нижче.
Без сумніву, Dispose слід викликати будь-які об'єкти, що закінчуються.
Таблиці даних є завершеними.
Calling Dispose значно прискорює повернення пам'яті.
MarshalByValueComponent викликає GC.SuppressFinalize (це) у своєму Dispose () - пропуск цього означає, що доведеться чекати десятки, якщо не сотні колекцій Gen0, перш ніж пам'ять буде відновлена:
З цього базового розуміння доопрацювання ми можемо вже вивести деякі дуже важливі речі:
По-перше, об’єкти, які потребують доопрацювання, живуть довше, ніж об'єкти, які цього не роблять. Насправді вони можуть прожити набагато довше. Наприклад, припустимо, що об’єкт, що знаходиться у gen2, потребує доопрацювання. Фіналізація буде запланована, але об'єкт все ще знаходиться у gen2, тому він не буде повторно зібраний до наступної колекції gen2. Це дійсно може бути дуже довгий час, і, насправді, якщо все піде добре, це буде довгий час, тому що колекції gen2 коштують дорого, тому ми хочемо, щоб вони траплялися дуже рідко. Старіші об'єкти, які потребують доопрацювання, можуть зачекати десятки, якщо не сотні колекцій gen0, перш ніж їх місце буде відтворено.
По-друге, об'єкти, які потребують доопрацювання, завдають пошкодження застави. Оскільки внутрішні покажчики об’єктів повинні залишатися дійсними, не тільки об'єкти, які потребують фіналізації, залишаться в пам'яті, але все, на що об'єкт посилається, прямо та опосередковано, також залишатиметься в пам'яті. Якщо величезне дерево об'єктів було закріплено одним об’єктом, який потребував доопрацювання, то все дерево затрималося б, можливо, протягом тривалого часу, як ми щойно обговорювали. Тому важливо економно використовувати фіналізатори та розміщувати їх на об'єктах, на яких є якомога менше внутрішніх покажчиків об'єктів. У прикладі дерева, який я щойно подав, ви можете легко уникнути проблеми, перемістивши ресурси, що потребують доопрацювання, до окремого об'єкта та зберігаючи посилання на цей об’єкт у корені дерева.
Нарешті, об’єкти, які потребують доопрацювання, створюють роботу для потоку фіналізатора. Якщо ваш процес доопрацювання є складним, один і єдиний потік фіналізатора витратить багато часу на виконання цих кроків, що може спричинити відставання роботи і, отже, призвести до того, що більше об'єктів затримається, чекаючи їх завершення. Тому життєво важливо, щоб фіналізатори виконували якомога менше роботи. Пам'ятайте також, що хоча всі покажчики об'єктів залишаються дійсними під час доопрацювання, можливо, ці вказівники призводять до об'єктів, які вже були остаточно завершені, і тому можуть бути менш корисними. Як правило, найбезпечніше уникати наступних покажчиків об’єктів у фіналізаційному коді, навіть якщо покажчики дійсні. Безпечний, короткий шлях до фіналізації - найкращий.
Візьміть це у того, хто бачив 100 000 МБ неопосиланих DataTables у Gen2: це надзвичайно важливо і повністю пропущено відповідями на цій темі.
Список літератури:
1 -
http://msdn.microsoft.com/en-us/library/ms973837.aspx
2 -
http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entry
http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage -collector-performance-using-finalizedispose-pattern.aspx
3 -
http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/