Todas as ideias sobre como escrever uma regra de análise estática (FXCop) para assegurar que os delegados de evento são removidos

StackOverflow https://stackoverflow.com/questions/854716

Pergunta

Estamos indo através de uma análise grande vazamento de memória e de ter encontrado um dos fatores que contribuem tem sido a não remoção de delegados em eventos causando objetos a não ser GCed rapidez suficiente (ou às vezes para sempre).

Será que alguém tem alguma idéia de como escrever uma regra no FXCop para garantir que temos os delegados são removidas manipuladores?

Eu vi este e como tal I' vai pedir lá para obter mais informações.

Foi útil?

Solução

Ok, ao lado do problema de implementar a verificação real (na minha opinião isso é muito semelhante a um caminho cobertura e, portanto, não é prático) - aqui é a maneira de escrever uma nova regra FxCop-lo:

À primeira alguns artigos que me ajudou uma vez:

A implementação de uma regra simples não é grande coisa. Em seu projeto, você precisa de um arquivo rules.xml como um recurso incorporado (ver aqui ). Você derivar a classe de BaseIntrospectionRule e adicionar seu código para o Check () - método:

public override ProblemCollection Check( TypeNode typeNode )
{
  if( type.IsPublic )
  {
    Problems.Add( new Problem( ... ) );
  }
  return Problems;
}

Eu fiz isso algumas vezes atrás. Espero que ele ainda funciona como descrito:)

Outras dicas

Você precisa ser mais específico. Você não precisa verificar se todos os delegados do evento foram subscritas, porque em um caso comum um assinante vive a vida mais curta do que uma editora. E um vazamento de memória só acontece quando o assinante parece ser de maior duração do que um editor, portanto, há uma referência, o que impede GC de coletar o objeto editor.

Agora precisamos verificar se se inscrever em um evento em um objeto relativamente curto de estar, você desinscrever de ele eventualmente.

Uma heurística eu posso vir acima com, neste caso: analisar todos os objetos de variável local (que estão no escopo do bloco de código atual {}) e todos os objetos, o que você explicitamente Dispose. Para cada evento sobre estes objetos contar o número de vezes que você assiná-los e o número de vezes que você cancelar a assinatura. Se o primeiro número é maior, em seguida, emitir um aviso.

É claro que não cobre todos os casos, mas acho que nenhuma abordagem estática pode cobrir todos os casos neste problema, você precisa de algum método que é bom o suficiente.

eu não vou mencionar as vantagens de análise dinâmica e revisões de código aqui, pois é um tópico separado, não relacionada com a questão.

Você pode forçar uma regra que todas as assinaturas de eventos devem ser tratadas através WeakReferences? Eu estou pensando que isso deve ser mais fácil de implementar do que ter que analisar o fluxo real de seu programa.

É seguro assumir os objetos que implementam os manipuladores de alguma forma têm referências para o objeto com os acontecimentos? Se for esse o caso, é melhor você descobrir como quebrar o ciclo de outra maneira.

Nós tivemos algo semelhante acontecendo há um tempo atrás com manipuladores de eventos em páginas ASP.NET. Os objetos que implementaram os manipuladores também tinha referências às páginas. Depois de quebrar o maior número de ligações architectually que pudemos, as poucas sobras foram alteradas para WeakReferences. Sem problemas mais memória!

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