В настоящее время я работаю над проектом, использующим 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();
}
}
Это то, на что я могу / должен положиться, работая без каких-либо побочных эффектов?
Пахнет так, как будто это может быть действительно плохой практикой.