Dispose não liberando memoria

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.

MemoryDispose1

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);
 }

}

Como executar aplicação como Administrador

Para executar uma aplicação win forms como administrador sempre que iniciar basta chamar este metodo no arquivo Program ou aonde estiver seu metodo Main da aplicação:

static void RunAsAdministrator()
 {
 ProcessStartInfo proc = new ProcessStartInfo();

proc.UseShellExecute = true;
 proc.WorkingDirectory = Environment.CurrentDirectory;
 proc.FileName = Application.ExecutablePath;
 proc.Verb = "runas";

 try
 {
 Process.Start(proc);
 }

catch
 {
 // The user refused the elevation.

// Do nothing and return directly ...

return;

}

Application.Exit();
 }

No main é interessante colocar esse pedaço de código assim você garante que o sistema já não está endo executado com privilégios de administrador

WindowsIdentity wi = WindowsIdentity .GetCurrent();
 WindowsPrincipal wp = new WindowsPrincipal(wi);
 bool isAdministrator = wp.IsInRole(WindowsBuiltInRole .Administrator);
 if (!isAdministrator)
 {
 RunAsAdministrator();
 }

O que é PACS? O que é DICOM?

Esse termos conhecidos na area de imagens médicas, mais não muito usuais para pessoas que não tem contato com essas terminologias, elas podem gerar uma certa confusão entre elas.

DICOM(Digital Imaging and Communications in Medicine): é um Protocolo para comunicação  informações e imagens médicas, ela se baseia em serviços para ser feito essa comunicação. Os arquivos transferidos por esse protocolo são de extensão DCM e contem além das imagens algumas informações, essa informações são diferenciadas dependendo de qual comando está sendo executado.
PACS(Picture Archiving and Communication System): é um Servidor que armazena as imagens médicas(DCM) e aceita o protocolo de comunicação DICOM. Ele deve ser apto a se comunicar com equipamentos de imagem medica e com máquinas que solicitem imagens, e qualquer outro equipamento que utilize o protocolo DICOM.
O básico de qualquer comunicação DICOM são as seguintes etapas:
  • Conexão: Inicio da Conexão aonde é passado para o servidor o IP e a porta utilizada para a comunicação e o servidor responde se a conexão é aceita ou não.
  • Associação: Garante se o nome da máquina(AeTitle na comunicação DICOM) é válido. Quando é solicitada uma associação o cliente informa qual comando e qual formato da transferência e seu retorno confirma se o servidor aceita ou não os comandos que podem ser executados.
  • Comando: envia as informações do comando e o retorno pode ser um ou varios retornos para cada comando executado
  • Release: confirma a desconexão entre o cliente e o servidor.

DICOM

Como Atualizar Banco de dados com NHibernate

Para atualizar o Schema do banco de dados utilizando NHibernate apenas é necessário utilizar esse comando:

NHibernate.Cfg.Configuration config = new NHibernate.Cfg.Configuration();
config.Configure("CaminhoArquivoConfig");
SchemaUpdate update = new SchemaUpdate(config);
update.Execute(false, true);

Para apenas gerar os scripts e não atualizar o banco é possível fazer desta forma:

public static string Script= "";
private static void Target(string comando)
{
 Script = Script + comando;
}
public static void AtualizarBD(){
NHibernate.Cfg.Configuration config = new NHibernate.Cfg.Configuration();
config.Configure("CaminhoArquivoConfig");
SchemaUpdate update = new SchemaUpdate(config);
update.Execute(Target, false);
}