есть проблема с перечислением изменений, когда DML и синхронизация выполняются одновременно. посмотрите на это исправление , если это поможет.
.Net Garbage Collector называет Объект. Завершите метод объекта на сборке "мусора". значение по умолчанию это делает ничто и должно быть переопределено, если Вы хотите освободить дополнительные ресурсы.
Располагают, автоматически не назван и должен быть explicity, названный, если средства должны быть высвобождены, такой, поскольку в рамках 'использования' или 'пробуют наконец' блок
, см. http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx для получения дополнительной информации
Я хочу подчеркнуть мысль Brian в его комментарии, потому что это важно.
Финализаторы не являются детерминированными деструкторами как в C++. Как другие указали, нет никакой гарантии того, когда это назовут, и действительно если у Вас будет достаточно памяти, если это будет когда-нибудь быть названным.
, Но плохая вещь о финализаторах то, что, как Brian сказал, она вызывает Ваш объект пережить сборку "мусора". Это может быть плохо. Почему?
, Как Вы можете или не можете знать, GC разделяется на поколения - Генерал 0, 1 и 2, плюс "Куча" для больших объектов. Разделение является широким термином - Вы получаете один блок памяти, но существуют указатели того, где Генерал 0 объектов запускаются и заканчиваются.
мыслительный процесс - то, что Вы будете, вероятно, использовать много объектов, которые будут недолгими. Таким образом, это должно быть легким и быстрым, чтобы GC добрался до - Генерал 0 объектов. Таким образом, когда существует давление памяти, первой вещью, которую оно делает, является Генерал 0 наборов.
Теперь, если это не разрешает достаточно давления, то оно возвращается и делает Генерала 1 развертка (восстанавливающий Генерала 0), и затем если все еще достаточно, оно делает Генерала 2 развертки (восстанавливающий Генерала 1 и Генерала 0). Так чистка долговечных объектов может требовать времени и быть довольно дорогой (так как Ваши потоки могут быть приостановлены во время операции).
Это означает это, если Вы делаете что-то вроде этого:
~MyClass() { }
Ваш объект, независимо от того, что, будет жить к Поколению 2. Это вызвано тем, что GC не имеет никакого способа назвать финализатор во время сборки "мусора". Таким образом, объекты, которые должны быть завершены, перемещены к специальной очереди, чтобы быть вычищенными другим потоком (поток финализатора - который, если Вы уничтожаете, заставляет все виды плохих вещей произойти). Это означает, что Ваши объекты бродят вокруг дольше и потенциально вызывают больше сборок "мусора".
Так, все это должно только убедительно доказать точку зрения, что Вы хотите использовать IDisposable для чистки ресурсов каждый раз, когда возможный и серьезно пытаются найти способы вокруг использования финализатора. Это находится в интересах Вашего приложения.
COUNT
действия на вложенном SELECT
, который имеет самое большее 1 строку (потому что эти LIMIT
находится в подзапросе).
– jpmc26
17 January 2014 в 11:37
Не в случае Вы описываете, Но GC будет звонить Финализатор для Вас, если у Вас будет тот.
КАК БЫ ТО НИ БЫЛО. Следующая сборка "мусора", вместо того, чтобы быть собранным, объект войдет в завершение que, все собрано, затем это - названный финализатор. Следующий набор после этого это будет освобождено.
В зависимости от давления памяти Вашего приложения, у Вас не может быть gc для того объектного поколения некоторое время. Таким образом в случае говорят, поток файла или соединение дб, Вам, вероятно, придется ожидать некоторое время, чтобы неуправляемый ресурс был освобожден в призыве финализатора некоторое время, вызвав некоторые проблемы.
Я не думаю так. Вы управляете, когда Располагают, назван, что означает, что Вы могли в теории писать код распоряжения, который делает предположения о (например), существовании других объектов. Вы не имеете никакого контроля, когда финализатор называют, таким образом, это было бы сомнительно, чтобы иметь финализатор, автоматически звонят, Располагают от Вашего имени.
<час>РЕДАКТИРОВАНИЕ: Я ушел и протестировал, только для проверки:
class Program
{
static void Main(string[] args)
{
Fred f = new Fred();
f = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Fred's gone, and he's not coming back...");
Console.ReadLine();
}
}
class Fred : IDisposable
{
~Fred()
{
Console.WriteLine("Being finalized");
}
void IDisposable.Dispose()
{
Console.WriteLine("Being Disposed");
}
}
GC будет не , вызов располагает. Это может называть Ваш финализатор, но даже это не гарантируется при всех обстоятельствах.
Посмотрите этот статья для обсуждения лучшего способа обработать это.
Шаблон IDisposable был создан, прежде всего, чтобы быть названным разработчиком, если у Вас есть объект, который реализует IDispose, который разработчик должен или реализовать using
ключевое слово вокруг контекста объекта или назвать Расположить метод непосредственно.
сбой, безопасный для шаблона, состоит в том, чтобы реализовать финализатор, назвав Расположение () метод. Если Вы не делаете этого, можно создать некоторые утечки памяти т.е.: Если Вы создаете некоторую обертку COM и никогда не называете Систему. Время выполнения. Interop. Маршалл. ReleaseComObject (comObject) (который был бы помещен в Расположить метод).
нет никакого волшебства в сбросе для вызова, Располагают методы автоматически кроме отслеживания объектов, которые содержат финализаторы и хранение их в таблице Finalizer GC и вызовом их, когда некоторая эвристика уборки умирает GC.
Уже существует большое хорошее обсуждение здесь, и я немного опаздываю стороне, но я хотел добавить несколько точек сам.
class SomeObject : IDisposable {
IntPtr _SomeNativeHandle;
FileStream _SomeFileStream;
// Something useful here
~ SomeObject() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
}
protected virtual void Dispose(bool disposing) {
if(disposing) {
GC.SuppressFinalize(this);
//Because the object was explicitly disposed, there will be no need to
//run the finalizer. Suppressing it reduces pressure on the GC
//The managed reference to an IDisposable is disposed only if the
_SomeFileStream.Dispose();
}
//Regardless, clean up the native handle ourselves. Because it is simple a member
// of the current instance, the GC can't have done anything to it,
// and this is the onlyplace to safely clean up
if(IntPtr.Zero != _SomeNativeHandle) {
NativeMethods.CloseHandle(_SomeNativeHandle);
_SomeNativeHandle = IntPtr.Zero;
}
}
}
Это - простая версия, но существует много нюансов, которые могут сбить Вас с толку на этом шаблоне.
, По-моему, намного лучше полностью постараться не иметь любые типы, которые непосредственно содержат и доступные ссылки и собственные ресурсы, которые могут потребовать завершения. SafeHandles обеспечивают очень очевидный способ выполнения этого путем инкапсуляции собственных ресурсов в доступные, которые внутренне обеспечивают их собственное завершение (наряду со многими другими преимуществами как удаление окна во время P/Invoke, где собственный дескриптор мог быть потерян из-за асинхронного исключения).
Просто определение SafeHandle делает это Тривиальным:
private class SomeSafeHandle
: SafeHandleZeroOrMinusOneIsInvalid {
public SomeSafeHandle()
: base(true)
{ }
protected override bool ReleaseHandle()
{ return NativeMethods.CloseHandle(handle); }
}
Позволяет Вам упрощать содержание типа до:
class SomeObject : IDisposable {
SomeSafeHandle _SomeSafeHandle;
FileStream _SomeFileStream;
// Something useful here
public virtual void Dispose() {
_SomeSafeHandle.Dispose();
_SomeFileStream.Dispose();
}
}
Документация относительно IDisposable дает довольно ясный и подробный explaination поведения, а также пример кода. GC НЕ будет звонить Dispose()
метод в интерфейсе, но он назовет финализатор для Вашего объекта.
Нет, это не называют.
, Но это делает легким не сделать, забывают располагать Ваши объекты. Просто используйте using
ключевое слово.
я сделал следующий тест для этого:
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
foo = null;
Console.WriteLine("foo is null");
GC.Collect();
Console.WriteLine("GC Called");
Console.ReadLine();
}
}
class Foo : IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposed!");
}