segunda-feira, 25 de fevereiro de 2008

C# e .NET - Thread - Usando MUTEX para fazer com que seu programa só execute uma instancia

O objetivo deste post é fazer com que só exista uma instancia do programa executando por vez.

Como vimos nos posts anteriores podemos "travar" um bloco de codigo para que ele só seja executado por uma thread por vez.
Então que tal bloquear toda a sua aplicação para que ela rode apenas uma por vez??
Como o MSN por exemplo que só roda um cliente na maquina por vez.
É obvio que se você usar o recurso lock não vai dar nenhum pouco certo, pois a nova instancia de seu programa será uma nova thread e ela vai executar normalmente aquele bloco de codigo porque para todos os efeitos o bloco da nova instancia é outro bloco.

Em C# podemos usar a classe Monitor, ao inves do lock como foi explicado no post anterior. A classe Monitor se comporta exatamente como o lock. Se ela se comporta da mesma maneira então não conseguiremos resultados diferentes.
Porém o sistema operacional tem um objeto que pode fazer a mesma coisa.
O nome dele é MUTEX.
Ele é cerca de 33 vezes mais lento do que usar a classe Monitor, porém ele pode bloquear peças de codigo entre diferentes AppDomains.
Descuple a falta de referencia mas esse dado da performance foi tirado do livro CLR via C#, infelizmente não lembro o nome do autor.
Isso é perfeito para o que queremos, pois duas instancias da nossa aplicação são duas appDomains diferentes.
Então vamos deixas as palavras de lado, já que eu não sou muito bom com elas, e começaremos a mostrar o codigo.

//Utilizamos a classe MUTEX
Mutex meuPrograma = null;

try
{
//essa declaração deve ser feita dentro do bloco try,
// pois se nao existir instancia do programa rodando ele vai gerar uma excessão
meuPrograma = Mutex.OpenExisting("PROGRAMA");

}
catch (WaitHandleCannotBeOpenedException) {
Console.WriteLine("Não existe Instancia do programa aberto");
}

if (meuPrograma == null)
{
meuPrograma = new Mutex(true, "PROGRAMA");
Console.WriteLine("Só pode haver um");
Console.ReadLine();
}
else {
Console.WriteLine("Já existe uma instancia rodando");
Console.ReadLine();
}

Vou deixar as explicações tecnicas um pouco de lado e explicar de maneira didatica.
Você vai criar uma aplicação, ela vai ter um "apelido" para o sistema operacional.
Quando for abrir uma nova aplicação o seu programa vai perguntar ao sistema operacional
se existe alguem rodando que tenha o mesmo apelido.
Caso exista ele vai exibir a mensagem "Já existe uma instancia rodando"
Caso não exista ele vai abrir seu programa normalmente.

Espero ter sido claro na explicação.

1 comentários:

Anônimo disse...

Cara, gostei da matéria sobre thread, parabéns.. é raro ver um blog de boa qualidade em material .NET , estou estudando para prova MCTS, estava estudando esta materia pelo livro, recorri a internet e vc explicou muito bem .. so tenho agradecer... vou começa a postar matérias futuramente.

Grato,

 
João Bosco Seixas