Task и утечка памяти (C#)

Рейтинг: 1Ответов: 1Опубликовано: 30.06.2023

Представим ситуацию, запускается новый Task через Task.Run(...) внутри происходит создание объекта, который взаимодействует с неуправляемыми ресурсами, но по неосторожности пропущен вызов высвобождения данных ресурсов. Вопрос в следующем: произойдёт ли высвобождения данных ресурсов или произойдёт утечка памяти? И Task будет ликвидирован или нет?

Ответы

▲ 6Принят

Неуправляемые ресурсы на то и неуправляемые, что пока их не освободит либо специально написанный для этого код, либо операционная система при закрытии процесса приложения, так и будут висеть в памяти.

К многопоточности это не имеет никакого отношения. А управляемые ресурсы, когда они не нужны, соберет Сборщик Мусора.

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

public class MyClass : IDisposable
{
    private IntPtr resource; // указатель на неуправляемый ресурс

    public MyClass()
    {
        resource = AllocateResource();
    }
    
    private IntPtr AllocateResource()
    {
        // выделение ресурса
    }

    private void FreeResource(IntPtr resource)
    {
        // очистка ресурса
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SupressFinalize(this); // говорит GC, что финализатор вызывать теперь не нужно
    }

    private bool disposed;

    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
            return;

        if (disposing)
        {
            // очистка управляемых ресурсов
        }

        // очистка неуправляемых ресурсов
        FreeResource(resource);
        disposed = true;
    }

    // финализатор, вызываемый GC
    ~MyClass()
    {
        Dispose(false);
    }
}

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