Back-End

29 ago, 2016

C# – Apresentando a classe Mutex

Publicidade

Neste artigo, vou apresentar a classe Mutex, seu conceito, suas propriedades, como podemos usá-la e um exemplo prático na linguagem C#.

O que é Mutex? Mutex é uma forma abreviada de mutually exclusive.

A definição da MSDN (numa tradução livre by Macoratti) diz o seguinte  sobre Mutex: “É um primitivo de sincronização que também pode ser usado para sincronização entre processos” (arre égua…).

fonte: https://msdn.microsoft.com/pt-br/library/system.threading.mutex%28v=vs.110%29.aspx

Na linguagem C#, Mutex é uma classe definida na livraria de classes da plataforma .NET (namespace System.Threading) que pode ser usada para prevenir a execução simultânea de um bloco de código por múltiplas threads que estão rodando em um processo único ou múltiplo.

Assim, Mutex é usado como um primitivo de sincronização em situações em que o recurso tem que ser compartilhado com múltiplas threads simultaneamente. Os objetos Mutex nomeados são usados para fazer a sincronização interprocessos, porque vários aplicativos podem acessar o mesmo objeto Mutex.

A classe Mutex foi projetada para proteger um recurso compartilhado, como memória, um identificador de arquivo ou uma conexão de rede de acesso simultâneo por vários segmentos ou processos.

Quando uma ou mais threads necessitam de acesso a um recurso partilhado ao mesmo tempo, o sistema necessita de um mecanismo de sincronização para garantir que apenas um segmento de cada vez utiliza o recurso.

Mutex é um primitivo de sincronização que concede acesso exclusivo para o recurso compartilhado para apenas uma thread. Se uma thread adquire um Mutex, o segundo segmento que quer adquirir esse Mutex é suspenso até que a primeira thread libere o Mutex. Isso ajuda a evitar a corrupção dos dados que pode ocorrer se não houver uma sincronização.

Um dos seus usos mais frequentes é verificar se há uma única instância de um aplicativo rodando ao mesmo tempo. Você pode criar objetos Mutex com um identificador único que podem ser abertos por outros processos e, assim, garantir que apenas uma instância está sendo executada no computador.

A seguir, vou mostrar dois exemplos básicos de usos da classe Mutex usando o VS 2013 Community e o VS 2015 Community.

Recursos usados:

1 – Usando Mutex e verificando se mais de uma instância está em execução

Neste exemplo, vamos criar uma aplicação Console e verificar se existe um objeto Mutex criado para definir se já existe uma instância em execução.

Abra o VS Community 2013  e clique em New Project.

A seguir, selecione Visual C# -> Windows -> Windows Forms Application.

Informe o nome Usando_Mutex e clique no botão OK.

mutex-1

Abra o arquivo Program.cs gerado no projeto e inclua o código abaixo:

using System;
using System.Threading;

namespace Usando_Mutex
{
    class Program
    {
        static Mutex _mutex;

        static bool IsSingleInstance()
        {
            try
            {
                // Tenta abrir um mutex existente
                Mutex.OpenExisting("MACORATTI");
            }
            catch
            {
                // se não existir um mutex ocorre uma exceção
                Program._mutex = new Mutex(true, "MACORATTI");

                // Existe somente uma instância
                return true;
            }
            // Sem exceção então existe mais de uma instância
            return false;
        }

        static void Main(string[] args)
        {
            if (!Program.IsSingleInstance())
            {
                Console.WriteLine("Existe Mais de uma instância em execução"); //sair
            }
            else
            {
                Console.WriteLine("Existe somente Uma instância em Execução"); //Continuar
            }
            Console.ReadLine();
        }
    }
}

O método OpenExisting() da classe Mutex abre um Mutex nomeado se ele já existir.

Se não existir uma instância do objeto Mutex, o método gera uma exceção em vez de criar o objeto do sistema. Para criar um objeto Mutex, podemos usar um dos construtores Mutex.

Para testar, eu vou abrir duas instâncias do Visual Studio abrindo o mesmo projeto e executar cada instância.

Na execução da primeira instância do VS, temos o seguinte resultado:

mutex-2

Executando a segunda instância do VS obtemos o resultado abaixo:

mutex-3

2 – Permitindo somente uma instância em execução

Neste exemplo, vamos criar uma aplicação Windows Forms e permitir somente uma instância da aplicação.

Abra o VS Community 2015  e clique em New Project.

A seguir, selecione Visual C# -> Windows -> Windows Forms Application.

Informe o nome Mutex_UmaInstancia e clique no botão OK.

A partir da ToolBox, inclua os seguintes controles no formulário form1.vb:

  • 1 Label – Executar Somente Uma Instância com Mutex

Abaixo leiaute do formulário:

mutex-4

O projeto em si não tem importância, o que vale é mostrar a utilização da classe Mutex.

Vamos fazer isso.

Abra o arquivo Program.cs e inclua o código abaixo:

using System;
using System.Threading;
using System.Windows.Forms;

namespace Mutex_UmaInstancia
{
    static class Program
    {
        // Define um nome Unico para sua aplicação
        static Mutex mutex = new Mutex(false, "Macoratti_App_ID");

        [STAThread]
        static void Main()
        {
            // espera por 3 seconds ate ter certeza de que não há outra instância sendo executada
            if (!mutex.WaitOne(TimeSpan.FromSeconds(3), false))
            {
                MessageBox.Show("Outra instância dessa aplicação já esta sendo executada");
                return;
            }

            try
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }
    }
}

Usamos o método WaitOne(int32, boolean) que bloqueia a thread atual até que a instância atual recebe um sinal, usando um TimeSpan para especificar o intervalo de tempo e especificar se deseja sair do domínio de sincronização antes do tempo de espera.

O método ReleaseMutex – Libera o Mutex. Ele será liberado quando a aplicação termina, mas mesmo se a aplicação terminar sem liberar o Mutex, ele será  automaticamente liberado pelo .NET Framework.

Para testar, vamos abrir duas instâncias do VS abrindo o mesmo projeto.

Ao executar o projeto pela primeira vez, teremos o seguinte resultado:

mutex-5

Na primeira vez, temos somente uma instância em execução e a aplicação é executada normalmente.

Executando a segunda instância, teremos o resultado a seguir:

mutex-6

Na segunda execução, o Mutex detecta que outra instância já está em execução e lança a exceção que capturamos e exibimos a mensagem acima.

Como a classe Mutex é um invólucro para uma construct Win32, ela requer transições de interoperabilidade que resultam em uma queda no desempenho.

Por esse motivo, ela não é uma boa opção, a menos que seu uso seja realmente necessário.

Pegue os projetos completos aqui: Usando_Mutex.zip (VS 2013)  e Mutex_UmaInstancia.zip (VS 2015).