Pergunta

Que recursos têm de ser limpos manualmente em C # e quais são as consequências de não fazê-lo?

Por exemplo, digamos que eu tenho o seguinte código:

myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
// Use Brush

Se eu não limpar o pincel usando o método de descarte, eu estou supondo que os liberta coletor de lixo da memória usado no término do programa? É este correto?

O que outros recursos que eu preciso para manualmente limpar?

Foi útil?

Solução

Tecnicamente nada que herda de IDisposable devem ser proativamente eliminados. Você pode usar o 'usando' declaração para facilitar as coisas.

http://msdn.microsoft.com/en-us/library /yh598w02.aspx

Às vezes, você vai ver uso inconsistente de IDisposable derivado objetos no código de exemplo documentação, bem como o código que é gerado por ferramentas (ou seja visual studio).

O que há de bom sobre IDisposable é que ele dá-lhe a capacidade de proativamente liberar o recurso não gerenciado subjacente. Às vezes você realmente quer fazer isso -. Pensar conexões de rede e recursos de arquivo, por exemplo,

Outras dicas

Se você não descarte alguma coisa, ele vai ser limpo quando os avisos de coletor de lixo que não há mais referências a ele em seu código, que podem ser depois de algum tempo. Para algo como isso, ele realmente não importa, mas para um arquivo aberto que provavelmente faz.

Em geral, se algo tem um método Dispose, você deve chamá-lo quando tiver terminado com ele, ou, se você puder, envolvê-lo em um comunicado using:

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}
  • alças para estruturas de dados Interno do Windows.
  • conexões de banco de dados.
  • alças arquivo.
  • Conexões de rede.
  • COM / referências OLE.

A lista continua.

É importante chamar Dispose ou mesmo ainda melhor, use o padrão using.

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}

Se você não descarte alguma coisa, ele vai ser limpo quando os avisos de coletor de lixo que não há mais referências a ele, que pode ser depois de algum tempo.

No caso de System.Drawing.Brush, o Windows irá manter estruturas de janelas internas para o pincel carregado na memória até que todos os programas de lançar seu punho.

As consequências de não descartar suas IDisposables pode variar de um acerto de desempenho insignificante para bater seu aplicativo.

O objeto da escova no seu exemplo vai ser limpos pelo GC quando se sente como ele. Mas seu programa não terá tido o benefício de que pouco de memória extra que você teria ganho por limpá-lo mais cedo. Se você estiver usando um monte de escova objetos isso pode tornar-se significativo. O GC também é mais eficiente na limpeza de objetos, caso não tenham sido em torno de muito tempo, porque é um coletor de lixo geracional.

Por outro lado, as consequências de não descartar objetos de conexão de banco de dados pode significar que você correr para fora de conexões de banco de dados agrupados muito rapidamente e causar seu aplicativo para acidente.

De qualquer uso

using (new DisposableThing...
{
    ...
}

Ou, se você precisa segurar uma referência a um IDisposable em seu objeto para sua vida, implementar IDisposable no seu objeto e chamar o método Dispose do IDisposable.

class MyClass : IDisposable
{
    private IDisposable disposableThing;

    public void DoStuffThatRequiresHavingAReferenceToDisposableThing() { ... }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    //etc... (see IDisposable on msdn)

}

Geralmente, qualquer coisa que implementa IDisposable deve causar-lhe para fazer uma pausa e pesquisar o recurso que você está usando.

GC só acontece quando há pressão de memória, de modo que você não pode prever quando. Embora um descarregamento do AppDomain certamente provocá-lo.

Como já foi dito, usando é seu amigo. Eu escrevi neste blog entrada sobre como implementar IDisposable de uma forma bastante simples que é menos propenso a erros por factoring fora as partes que são o mais importante.

Um truque que eu uso quando eu não me lembro se um determinado objeto é um recurso descartável é digitar ".Dispose" (no máximo!) Após a declaração para obter Intellisense para verificar para mim:

MemoryStream ms = new MemoryStream().Dispose

Em seguida, exclua o .Dispose e usar a diretiva usando ():

using(MemoryStream ms = new MemoryStream())
{
  ...
}

Bem, contanto que você usar a versão gerenciada dos recursos e não chamar as APIs do Windows por si mesmo, você deve estar OK. Apenas se preocupar em ter que apagar / destruir um recurso quando o que você recebe é um IntPtr, como "pegas janelas" (e um monte de outras coisas) são conhecidos em .NET, e não um objeto.

A propósito, o recurso (como qualquer outro objeto .NET) será sinalizado para a coleta assim que deixar o contexto atual, então se você criar a escova dentro de um método, ele será sinalizado quando sair dele.

Se ele conseguiu (ou seja, parte do quadro), você não precisa se preocupar com isso. Se ele implementa IDisposable apenas envolvê-la em um bloco using.

Se você quiser usar recursos não gerenciados, então você precisa ler sobre finalisers e implementação de IDisposable si mesmo.

Há muito mais detalhes sob esta questão

Em primeiro lugar após o término do programa, você pode assumir que a memória usada pelo processo será eliminado com o próprio processo.

Enquanto estiver usando dispor ou destruidor in.net, é preciso entender que o tempo de quando a função de descarte é chamado pelo GC é não-determinista. Por isso recomenda-se usar o usar ou ligar para o descarte de forma explícita.

Ao usar recursos, como arquivos, memória objetos como semaphors e recursos que fora ao vivo do mundo gerenciado do .net devem ser libertados.

O SolidBrush por exemplo, você precisa descartar, porque é um objeto GDI e que vivem fora do mundo .net.

O coletor de lixo não é só liberar no término do programa, caso contrário não seria realmente útil (em qualquer sistema operacional decente / recente, quando o processo é encerrado, toda a memória é limpa automaticamente pelo sistema operacional de qualquer maneira).

Uma das grandes vantagens de C # comparação com C / C ++ é que você não precisa se preocupar com liberando objetos alocados (na maioria das vezes pelo menos); o gc faz isso quando o tempo de execução decide (várias estratégias quando / como fazê-lo).

Muitos ressources não são atendidos pelo gc: file, ressources relacionados com rosca (fechaduras), conexões de rede, etc ...

Um lugar para ter cuidado é objetos que o olhar pequeno para GC, mas não são ... Na API do SharePoint, por exemplo, o objeto SPWeb tem uma pegada pequena, tanto quanto o GC está em causa e por isso terá prioridade baixa para a coleta, mas tem realmente pegou um monte de memória (no heap eu acredito) que o GC não sabe sobre. Você vai correr em alguns problemas de memória divertido se você está foreaching um monte delas, por exemplo, lembre-se sempre de usar usar ou dispor!

Ao invés de pensar em um objeto como "segurando" os recursos que precisam ser liberado, é melhor pensar em termos de um objeto como tendo alterado alguma coisa (possivelmente fora do computador!) Que irá sobreviver a isso, de certa forma poderia ser prejudicial se não desfeita ou "limpo", mas que apenas o objeto pode limpar. Enquanto esta alteração normalmente assume a forma de um objeto concreto em uma piscina que está sendo marcado "ocupado", a sua forma exata não importa. O que importa é que as mudanças precisam ser desfeita, eo objeto contém informações necessárias para fazer isso.

O coletor de lixo irá lidar com quaisquer recursos gerenciados. No seu exemplo, a escova vai ser limpo quando o coletor de lixo decide, o que vai acontecer algum tempo após a última referência para o pincel não é mais válido.

Há certas coisas que precisam ser limpos manualmente, mas esses são os ponteiros recuperados a partir de fontes não gerenciados, como chamadas DLL, nada dentro do .NET Framework precisa desse tratamento no entanto.

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