Pergunta

Estou tentando escrever um gerente de recursos simples para o pequeno jogo de hobby que estou escrevendo. Uma das tarefas que esse gerente de recursos precisa executar é descarregar recursos não utilizados. Eu posso pensar em fazer isso de duas maneiras:

  • Quando um objeto não requer mais uma referência ao recurso, ele deve chamar um método do gerenciador de recursos para significar que não o está mais usando; ou

  • Quando um objeto não requer mais uma referência ao recurso, ele simplesmente o define como NULL. Então, quando o gerente de recursos é solicitado a descarregar recursos não utilizados, ele obtém a contagem de referência (via reflexão?) De cada recurso. Se a contagem de referência for uma (o gerente de recursos terá uma referência ao recurso), descarregue o recurso.

Existe alguma maneira de alcançar a segunda solução em C#? Obrigado.

Foi útil?

Solução

Parece -me que você poderia usar WeakReference do gerente de recursos. O GC fará o resto. Você precisará fazer um pouco de elenco, mas será simples e funcionará.

class Manager {
    Dictionary<string, WeakReference> refs =
        new Dictionary<string, WeakReference>();
    public object this[string key] {
        get {
            WeakReference wr;
            if (refs.TryGetValue(key, out wr)) {
                if(wr.IsAlive) return wr.Target;
                refs.Remove(key);
            }
            return null;
        }
        set {
            refs[key] = new WeakReference(value);
        }
    }
}
static void Main() {
    Manager mgr = new Manager();
    var obj = new byte[1024];
    mgr["abc"] = obj;

    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // true (still ref'd by "obj")

    obj = null;
    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // false (no remaining refs)
}

Outras dicas

Casal coisas. Primeiro, os objetos não são contados de referência; Os esquemas de contagem de referência têm o problema de referência circular, pelo qual dois objetos se referem um ao outro, mas são inacessíveis e, assim, vazam. O .NET usa uma abordagem de marcação e varredura que não usa a contagem de ref.

Segundo, embora a sugestão de usar uma referência fraca não seja terrível, também não é um slam dunk. Você está construindo um cache por razões de desempenho. (Suponho que sua pesquisa cuidadosa, empírica e realista sobre as características de desempenho do seu aplicativo demonstrou de forma convincente que uma estratégia de cache é necessária para alcançar um desempenho aceitável; se esse não for o caso, você está tomando essas decisões prematuramente.) Todo O Cache precisa ter uma política sobre quando libera seus recursos, caso contrário, é um vazamento de memória.

Como você sabe que a política do GC e sua política são políticas equivalentes? O GC não foi projetado com o seu específico necessidades de desempenho em mente. Ou seja, foi projetado para liberar recursos que realmente são lixo, para não atingir qualquer objetivo de desempenho específico que você tenha em mente. Ao delegar a decisão ao GC, você desiste da sua capacidade de ajustar sua política de cache às suas necessidades de desempenho.

Já temos um gerente de recursos na .NET, chamado de coletor de lixo. Portanto, uma abordagem muito eficiente é definir as referências a NULL e não fazer nada.

Uma resposta mais direta: não, não há como obter as referências para um objeto.

Você pode querer estudar o Classe de Referência fraca ou use um sistema de cache.

Verifique se o gerente de recursos usa WeakReferences para seus recursos. Dessa forma, quando ninguém mais estiver referenciando os recursos, eles serão elegíveis para a coleta de lixo.

Como já contado por outros usuários, o que você está tentando alcançar já é feito pelo GC e pode ser bem ajustado usando um Referência fraca.

Isso implica que em ambientes gerenciados como .NET, Java e assim por diante, este é um não problema.

Como a arquitetura-estrutura de baixo nível o isola do gerenciamento de memória, se você ainda precisar para esse tipo de funcionalidade, sugiro fortemente que você revise sua própria arquitetura de código, porque isso significaria que você está fazendo algum tipo de má prática em Gerenciamento de memória

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top