Неуправляемые ресурсы на то и неуправляемые, что пока их не освободит либо специально написанный для этого код, либо операционная система при закрытии процесса приложения, так и будут висеть в памяти.
К многопоточности это не имеет никакого отношения. А управляемые ресурсы, когда они не нужны, соберет Сборщик Мусора.
Для того чтобы передать внутренние неуправляемые ресурсы под охрану Сборщику, правильные разработчики реализуют для классов 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);
}
}
Таким образом можно забыть про то что неправильное использование класса приведет к утечкам памяти. Так как если даже разработчик забудет задиспозить класс, это сделает Сборщик, когда он станет не нужен.