Обработка совместного владения неуправляемыми ресурсами с воскрешением объекта - PullRequest
1 голос
/ 12 июля 2020

В настоящее время я работаю над проектом, использующим OpenGL через библиотеку OpenTK. Объекты OpenGL, такие как буферы или шейдеры, являются неуправляемыми ресурсами, которые имеют целочисленный идентификатор. Большинство объектов в моей программе ссылаются на ресурс OpenGL. Также очень часто один и тот же ресурс используется несколькими разными объектами.

Все ресурсы OpenGL являются производными от класса GLObject, реализующего IDisposable. Когда вы имеете дело с единоличным владельцем, ручной вызов Dispose() работает нормально. Однако при совместном владении у вас есть проблема, заключающаяся в том, что вы больше не знаете, когда на самом деле вызывать Dispose ().

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

В итоге я просто позволил моим объектам собирать мусор без удаления и затем воскресите их в очередь мусора:

abstract class GLObject : IDisposable
{
    public int ID { get; protected set; }

    ~GLObject()
    {           
        Renderer.garbage.Enqueue(this);
    }

    public void Dispose()
    {
        FreeGPURessource();

        GC.SuppressFinalize(this);
    }

    public abstract void FreeGPURessource();
}

.

public static ConcurrentQueue<GLObject> garbage = new ConcurrentQueue<GLObject>();

В подходящий момент мое приложение затем вызывает метод CollectGarbage () из правильного потока:

public static void CollectGarbage()
{
    while (garbage.TryDequeue(out GLObject ressource))
    {
        ressource.Dispose();
    }
}

Это то, на что я могу / должен положиться, работая без каких-либо побочных эффектов?

Пахнет так, как будто это может быть действительно плохой практикой.

...