C # / CLI: деструктор не вызывается, если в нем используется Dispose ()

У меня есть класс C ++ / CLI с именем «CTransferManaged» с реализованным финализатором и деструктором:

CTransferManaged::~CTransferManaged()
{
this->!CTransferManaged();
}
CTransferManaged::!CTransferManaged()
{
//Clean up resources...
}

Этот класс обернут классом C # с именем «CTransfer», содержащим объект m_transfer типа CTransferManaged.

Если деструктор этого класса очищает только ссылку на объект m_transfer, я вижу, что деструктор вызывается (точка останова нажата):

~CTransfer()
{
m_transfer = null; //breakpoint on this line
}

Если я вызываю функцию Dispose () объекта m_transfer, ничего не меняя, деструктор больше не вызывается (точка останова больше не попадает). Есть догадки почему?

~CTransfer()
{
m_transfer.Dispose(); //breakpoint on this line
m_transfer = null;
}

Я хотел бы вызвать Dispose () вручную, так как я обнаружил, что ресурсы объекта C ++ / CLI (m_transfer) не очищаются должным образом, если я не вызываю Dispose вручную. На данный момент я не знаю точно, почему.

Почему деструктор CTransfer (класс C #) больше не вызывается, как только он вызывает CTransferManaged :: Dispose () (C ++ / CLI)?

5

Решение

Деструктор C # вызывается только сборщиком мусора, и вы не можете вызвать его напрямую.

Dispose, являющийся частью интерфейса IDisposalbe, должен вызываться только вручную, и он не будет запускать деструктор.

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

Если класс Resource содержит внедренные объекты, которые должны быть расположены, этот шаблон необходим с C #:

// C#
public class Resource : IDisposable
{
private EmbeddedResource embedded;

public Resource()
{
Console.WriteLine("allocating resource");
embedded = new EmbeddedResource();
}

~Resource()
{
Dispose(false);
}

protected virtual void Dispose(bool disposing)
{
Console.WriteLine("release resource");
if (disposing)
{
embedded.Dispose();
}
}

public void Dispose()
{
Dispose(true);
}
}
0

Другие решения

Типичный шаблон для удаления и финализации таков, что когда вы вызываете Dispose, финализатор должен быть подавлен. Dispose предназначен для очистки ресурсов, как только он выполняется, тогда как финализатор предназначен для очистки ресурсов всякий раз, когда сборщик мусора собирает класс … Оба предназначены для того же действия (освобождение неуправляемых ресурсов), и поэтому, если вы вызываете Уничтожение, вызов финализатора будет лишним и ненужным, а также приведет к тому, что объект будет жить дольше, чем нужно, так как он будет сначала помещен в очередь финализатора, прежде чем будет собран и уничтожен. Это приводит к плохому управлению памятью в приложениях с высоким уровнем доступа, которые создают и располагают много объектов. Поэтому большинство методов Dispose в C # будут вызывать:

GC.SuppressFinalize(this);

Что говорит сборщику мусора не делать финализатор. Этот шаблон широко используется и, вероятно, также используется в вашем неуправляемом классе. Вероятно, поэтому вызов Dispose удаляет деструктор.

0

По вопросам рекламы [email protected]