Pergunta

Eu tenho um problema com um vazamento de memória em um aplicativo .NET CF.

Usando RPM I identificou que criar dinamicamente controles não são lixo coletado como esperado. Executando o mesmo pedaço de código em .NET Janela Formas se comportam de forma diferente e dispõe de controle como eu esperava.

Veja a saída do RPM via PerfMon para o Processo Heap Contador:
text alt

GC Heap:
text alt

Meu melhor palpite é que a referência fraca para o Painel é por algum motivo desconhecido não fazer o objeto se qualifique para o GC, pode ser?

Por favor nota: Mesmo que Dispose () resolve o problema para a amostra, não posso facilmente incorporá-la no aplicativo existente, uma vez que não é tão clara para determinar quando o objeto não está mais em uso.

Eu incluí uma versão simplificada da fonte para ilustrar o problema:

using System;
using System.Windows.Forms;

namespace CFMemTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Calling this event handler multiple times causes the memory leak
        private void Button1_Click(object sender, EventArgs e)
        {
            Panel uc = new Panel();
            // Calling uc.Dispose() cleans up the object 
        }
    }
}

Update:
1. chamada GC.Collect () também não resulta em painéis de ser limpo.
2. Usando .NET CF 2.0 SP1 em um 4.2 dispositivo Windows CE.

Foi útil?

Solução

Algumas informações adicionais aqui que explica este comportamento.

De acordo com Ilya Tumanov :

Tudo UI relacionados em NETCF é intencionalmente removido de CG, de forma escopo nunca é coletado . Esse comportamento é diferente do ambiente de trabalho e tem sido mudado em NETCF V3.5 (a não ser correr em modo de compatibilidade).

É tão diferente, porque IU conseguiu aulas sobre NETCF são completamente diferente de desktop. Eles são finos invólucros mais de implementação nativa que foi necessário para alcançar aceitável desempenho.

Eu não tenho certeza que há um tal recurso. Mas, realmente, tudo o que você precisa saber é: nunca é coletado, deve chamar descarte. Você realmente deve fazer isso na área de trabalho tão bem, mas se você não sua forma mais perdoando. Não em breve NETCF.

Outras dicas

Um formulário não dispõe automaticamente todos os controles criados em seu código, porque não tem nenhuma maneira de saber que ela existe. Para obter o formulário para Formulário para Dispor automaticamente quando é Disposed, você precisa adicioná-lo à coleção Controls.

Agora, no seu caso que não pode fazer nada. Eu não posso dizer se o seu exemplo é planejado, ou do mundo real. Se é no mundo real, então o comportamento é esperado, como o Painel não se recolhido quando a variável sai do escopo (não tenho certeza que ele faz no ambiente de trabalho quer). Torna-se disponível para a coleta, mas isso simplesmente significa que na próxima coleção passá-lo será varrido. A menos que você está causando um GC, então ele não vai ser liberado.

Eu recomendo que você dê uma olhada no MSDN webcast sobre o gerenciamento de memória no CF . Ele fornece uma explicação muito mais completa sobre o que está acontecendo sob o capô -. Muito mais do que nós poderíamos fornecer em uma resposta aqui

Você tem certeza que você tem um vazamento de memória? O coletor de lixo .NET Compact Framework funciona de forma ligeiramente diferente ao que, no quadro completo .NET. De de Steven Pratschner blogue :

Uma coleção é iniciada quando:

  • 1MB de objetos foram alocados,

  • Um aplicativo é movido para o fundo,

  • Uma falha ao atribuir memória ocorre

  • Um aplicativo chama GC.Collect.

Eu acho que você precisa remover dinamicamente o botão de clique EventHandler também, como você pode ver a partir deste blog: http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using-the-net-cf-remote-performance-monitor.aspx

É a partir Steven Pratschner também.

A propósito, o webcast mencionado acima está ligado aqui: http://msevents.microsoft.com/cui/ WebCastEventDetails.aspx? cultura = pt-bR & EventID = 1032318791 & CountryCode = US

Espero que isso ajude!

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