Esse caso é difícil de ocorrer , porém foi um problema que eu demorei pelo menos uma semana para entender o que estava ocorrendo com isso vou passar o que ocorreu:
Eu tinha dois Windows Form que um abria o outro, porém quando abria esse segundo form era alocado 150MB de RAM para esse novo form, mais quando ele era fechado esses 50MB se mantinham na memoria e se após era aberto novamente esse form era alocado novamente mais 150MB e quando fechava mantinha 50Mb isso ia acumulando e acabava depois de um tempo de uso travando o sistema, e sendo necessário reabrir o sistema.
Entendido o problema que ocorre, agora vamos ao motivo do problema, o problema é causado por eventos relacionado entre os forms, bom isso não é muito explicativo né mais vou tentar ser bem claro:
digamos que o Form1 é o principal e o Form 2 é o que é aberto, o que acontece é que o Form 2 seta um evento do form1, vou dar um exemplo programático:
Form1
Form2 f = new Form2(this); f.Show();
Form2
<pre>public Form2(Form1 form1) { this.Form1 = form1; InitializeComponent(); form1.FormClosed += form1_FormClosed; } protected Form1 Form1 { get; set; } void form1_FormClosed(object sender, FormClosedEventArgs e) { MessageBox.Show("teste"); }
Isso é um problema quando os forms possuem muitos controles ou com user controles com informações pesadas, pois essas se mantem na memoria e não saem até que seja removido essa reverencia de eventos, isso é mais um problema de codificação ou de analise, pois não é uma boa pratica fazer isso, pois faz com que o sistema fique uma bagunça para entender alguma rotina.
SOLUÇÕES
1. Refatoração do Código
Fazer uma analise e remover a dependência entre os forms, para melhorar a codificação do sistema
2. Remover o Evento no Dispose
Colocar no Dispose do form para Remover o evento criado, para o exemplo acima ficaria assim:
protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } Form1.FormClosed -= form1_FormClosed; base.Dispose(disposing); }
3. Remover evento dinamicamente
Para remover eventos dinamicamente você pode utilizar esse método que irá ajudar.
public static void RemoveEvents(object ctrl) { Type t = ctrl.GetType(); EventInfo[] eventInfos = t.GetEvents(); foreach (EventInfo fieldInfo in eventInfos) { FieldInfo field = t.GetField(fieldInfo.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase); if (field == null) continue; object value = field.GetValue(ctrl); if (value == null) continue; fieldInfo.RemoveEventHandler(ctrl, (Delegate)value); } }