2008-10-21 2 views
3
SqlConnection connection = new SqlConnection(FROM_CONFIGURATION) 
SqlCommand command = new SqlCommand("SomeSQL", connection); 
connection.Open(); 
command.ExecuteNonQuery(); 
command.Dispose(); 
connection.Dispose(); 

Рекомендуется, чтобы приведенный выше код включал try/catch (или использование), чтобы при возникновении исключения все ресурсы были расположены правильно.Какой смысл сборщика мусора?

Но если вам нужно беспокоиться об утилизации вручную, тогда какая точка GC! Разве GC там не позаботиться об этом для кодера?

+1

Хороший вопрос для тех, кто заинтересован в оптимизации своего кода. – Kon 2008-10-21 19:47:14

+3

Как это связано с оптимизацией кода? – 2008-10-21 19:54:51

ответ

1

вышеупомянутый код освобождает приобретенные ресурсы (хотя, я не думаю, что вы должны сами вызвать метод Dispose(), выпуская ресурсы, это означает закрытие потоков и тому подобное). GC удаляет объект из памяти (освобождает память, используемую объектом), но это может быть сделано только после освобождения ресурсов объектом.

+1

Вы должны обязательно вызвать Dispose() для объектов, с которыми вы закончили (или использовать с помощью, что делает то же самое). – 2008-10-21 19:52:47

6

Но если вам не придется беспокоиться о УТИЛИЗАЦИИ вещи вручную, то что точка GC ?! Разве это не GC , чтобы позаботиться об этом для кодера?

Проблема в том, что у вас нет идеи , когда GC будет работать. И если ваше приложение никогда не нажимает на память, оно может вообще не работать.

+2

... и некоторые ресурсы намного реже, чем память. – 2008-10-21 19:41:36

1

Я не уверен в том, что C#, как это выглядит, но обычно сборщик мусора управляет памятью. Это соединение, помимо памяти объекта, имеет серверные ресурсы. База данных, которая находится в отдельном процессе, должна поддерживать соединение. Закрытие очищает их.

0

GC позаботится об утилизации объектов, но удаление может не произойти сразу. Ручное удаление объектов ускорит работу памяти быстрее.

0

GC ограничен, когда речь идет об освобождении внешних ресурсов, таких как соединения DB или файлы. Однако для распределения памяти в мире .NET он заботится о многих задачах управления памятью.

2

Поскольку GC не является наиболее эффективным - это происходит не всегда, как только ресурс больше не используется. Поэтому, когда вы имеете дело с неуправляемыми ресурсами, такими как файловые ввода-вывода, соединения с БД и т. Д., Лучше всего выпустить/очистить эти ресурсы до ожидания и полагаться на GC, чтобы позаботиться об этом.

И смотреть в использовании using ключевое слово:

using (SqlConnection connection = new SqlConnection(FROM_CONFIGURATION)) 
using (SqlCommand command = new SqlCommand("SomeSQL", connection)) 
{ 
    connection.Open(); 
    command.ExecuteNonQuery(); 
    command.Dispose(); 
    connection.Dispose(); 
} 

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

+1

Если вы используете инструкцию using, вам не нужно явно вызывать метод Dipose(), то есть весь смысл использования «использования». – IAmCodeMonkey 2008-10-21 19:51:41

+0

Я бы не стал говорить, что GC не эффективен, поскольку он не возникает, как только ресурс больше не используется. Часть собранной мусором времени выполнения заключается в том, что она не является детерминированной и работает только тогда, когда она определяет необходимость ее запуска. – 2008-10-21 19:52:40

4

Объекты, реализующие IDisposable, пытаются сказать вам, что они имеют связи с структурами, которые не управляются. Сборщик мусора работает партиями, чтобы повысить эффективность. Но это означает, что может быть некоторое время, прежде чем ваш объект будет удален, что означает, что вы будете удерживать ресурсы дольше, чем вы должны быть, что может иметь негативные последствия для производительности/надежности/масштабируемости.

15

Как говорят другие люди, GC не является детерминированным, поэтому вы не знаете, когда ваш объект будет собран. Я хочу уточнить, что это не проблема с памятью, а с системными ресурсами (открытыми файлами, соединениями с базой данных), которые являются дорогостоящими и должны быть выпущены как можно скорее. Dispose позволяет вам это делать, когда вы знаете, что больше не используете соединение. Если они не будут выпущены вовремя, система может исчерпать эти ресурсы, и GC не знает об этом. Вот почему вы должны делать это вручную.

Также я хочу добавить, что использование инструкции «using» сделает это для вас красиво.

3

GC запускает время от времени и заботится об управлении памятью, сохраняя все хорошее и аккуратное для вас. Вы можете думать, что это бесполезно, когда вы видите фрагменты кода, подобные тому, который вы опубликовали, но чаще всего это сэкономит вам много головных болей (подумайте о ручном управлении памятью C/C++), поскольку это значительно уменьшает утечки памяти и позволяет вам беспокоиться о том, как будет работать ваше приложение, а не о том, как вы будете управлять памятью. Устранение связей с файлами и подключений к базам данных является способом повышения эффективности, поскольку сбор мусора не является детерминированным и может не произойти сразу, и вы не хотите, чтобы эти дескрипторы файлов и открытые соединения с базой данных подрывали производительность вашей системы. Кстати, ваш код действительно некрасиво, я всегда выступаю за помощью заявления и часто писать мой дб код вроде этого:

using (SqlConnection connection = new SqlConnection(...)) 
using (SqlCommand command = connection.CreateCommand()) 
{ 
    ... 
} 

Это автоматически вызывает выбрасывайте на связь и командных объектах, когда они выпадают из сферы, который при исполнении покидает блок.

1

Сборщик мусора (GC) в .NET является основной частью .NET Common Language Runtime (CLR) и доступен для всех языков программирования .NET. GC никогда не предназначался для управления ресурсами; он был разработан для управления распределением памяти, и он отлично справляется с управлением памятью, выделенной непосредственно на собственные .NET-объекты. Он не был предназначен для работы с неуправляемой памятью и оперативной памятью, поэтому разработчик должен управлять этими ресурсами.

В конкретном случае подключения к базе данных вы имеете дело с другими ресурсами, а не только с памятью - в частности пулы соединений, возможные неявные области транзакций и т. Д. Вызывая Close() и/или Dispose(), вы явно указываете объект немедленно освободить эти неуправляемые ресурсы, в то время как управляемые ресурсы будут ждать появления цикла GC.

7

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

Существуют различные причины, по которым расширение GC для выпуска других ресурсов проблематично. Один из них заключается в том, что финализаторы (методы, выполняемые при сборе мусора) делают ссылочные циклы нецелесообразными, если вы не сильно ограничиваете разыменование из финализаторов, что делает их очень сложными в использовании.

Другая причина заключается в том, что большинство ресурсов необходимо отменить в какой-то своевременной форме, что невозможно, если полагаться на сборку мусора.

Еще одна причина заключается в том, что ограничение GC для управления памятью сделок с огромной насыпи управления ресурсами в любом приложении, и почти все не интересной управления ресурсами. Другие ресурсы, как правило, достаточно интересны, заслуживают некоторого дополнительного кода, чтобы быть явным о том, как они выпущены.

И еще одна причина в том, что в некоторых приложениях приложение GC ускоряет работу, поскольку оно уменьшает количество копий, выполненных для удовлетворения семантики владения. Это не проблема для других ресурсов.

Другие люди могут продолжать это в течение нескольких часов.

0

Вышеприведенный пример, когда изначально выделенная память или ресурсы перемещаются в управляемый мир в качестве дескриптора. В этом сценарии, потому что управляемый мир не выделял память, он не может «автоматически убрать» его.Память/ресурсы должны быть явно удалены или, по крайней мере, расположены в финализаторе.

В подавляющем большинстве случаев, особенно когда речь идет о коде, критическом для большинства основных целей компании (бизнес-логики компании), вам не нужно беспокоиться об этом, и меньше кода означает меньше ошибок.

5

Предположим, у меня есть этот код:

class MonkeyGrabber : IDisposable { 
    public MonkeyGrabber() { /* construction grabs a real, live monkey from the cage */ 
    public void Dispose() { Dispose(true); /* releases the monkey back into the cage */ } 
    // the rest of the monkey grabbing is left as an exercise to grad student drones 
} 

class MonkeyMonitor { 
    public void CheckMonkeys() { 
     if (_monkeyPool.GettingTooRowdy()) { 
      MonkeyGrabber grabber = new MonkeyGrabber(); 
      grabber.Spank(); 
     } 
    } 
} 

Теперь мой MonkeyMonitor проверяет обезьян, и если они слишком шумные, он получает ценный ресурс системы - один обезьяну захватывая лапу, прикрепленную к системе, и использует его, чтобы схватить обезьяну и отшлепать ее. Поскольку я не распоряжался им, обезьянник все еще держится за обезьяну, висящую над ним. Если остальные обезьяны продолжают становиться шумными, я не могу создать новый MonkeyGrabber, поскольку он все еще помогает. К сожалению. Надуманный пример, но вы понимаете: объекты, реализующие IDisposable, могут иметь ограниченные ресурсы, которые должны быть выпущены своевременно. ГК может уйти в конце концов или нет.

Кроме того, некоторые ресурсы необходимо своевременно выпускать. У меня есть набор классов, которые, если они не будут удалены ни приложением, ни с помощью GC до выхода приложения, приведет к жесткому сбою приложения, поскольку неуправляемый менеджер ресурсов, из которого они пришли, уже ушел к тому времени, когда GC приближается к нему ,

More on IDisposable.

using is your friend - это самый близкий к настоящему моменту до RAII.

2

... GC никогда не предназначался для управления ресурсами; он был разработан, чтобы управлять распределением памяти ... В конкретном случае соединений с базой данных, вы имеете дело с другими ресурсами, чем просто память ... (Scott Дорман)

ОП не помечать с конкретным хотя большинство ответов были .net-specific, отметив, что GC в основном для предотвращения утечек памяти, но расширения, такие как выражения using и IDisposable, могут многое помочь.

Другие платформы предлагают другие решения. Например, в C++ нет (встроенной) сборки мусора, но некоторые формы общих указателей могут использоваться для управления памятью, а стиль кодирования RAII может быть чрезвычайно полезен при управлении другими типами ресурсов.

В cPython используются две различные системы сбора мусора. Реферирующая реализация подсчета сразу же вызывает деструкторы, когда последняя ссылка удалена. Для обычных «стековых» объектов это означает, что они немедленно очищаются, например, что происходит для объектов C++ RAII. Недостатком является то, что если у вас есть эталонный цикл, сборщик подсчета ссылок никогда не удалит объект. В результате у них есть вторичный не детерминированный сборщик мусора, который работает как сборщики Java и .NET. Подобно .NET с его помощью, cPython пытается обрабатывать наиболее распространенные случаи.

Таким образом, для ответа на ОП недетерминированная сборка мусора помогает упростить управление памятью, она также может использоваться для обработки других ресурсов, поскольку своевременность не является проблемой, а другой механизм (например, тщательное программирование, ссылка подсчет GC, оператор using или реальные объекты RAII) необходимы, когда требуется своевременное выделение других ресурсов.

1

А теперь я вижу. Я путал управление памятью с неуправляемым управлением ресурсами. Спасибо за разъяснение!

Смежные вопросы