47 votes

L'utilisation d'un mutex pour empêcher plusieurs instances du même programme de s'exécuter en toute sécurité?

J'utilise ce code pour empêcher une deuxième instance de mon programme de s'exécuter en même temps, est-il sécurisé?

 Mutex appSingleton = new System.Threading.Mutex(false, "MyAppSingleInstnceMutx");
if (appSingleton.WaitOne(0, false)) {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new MainForm());
    appSingleton.Close();
} else {
    MessageBox.Show("Sorry, only one instance of MyApp is allowed.");
}
 

Je crains que si quelque chose lève une exception et que l'application se bloque, le Mutex aura toujours lieu. Est-ce vrai?

67voto

Anton Tykhyy Points 12680

Il est plus habituel et pratique d’utiliser les événements Windows à cette fin. Par exemple

 static EventWaitHandle s_event ;

bool created ;
s_event = new EventWaitHandle (false, 
    EventResetMode.ManualReset, "my program#startup", out created) ;
if (created) Launch () ;
else         Exit   () ;
 

Lorsque votre processus se termine ou se termine, Windows ferme l'événement pour vous et le détruit s'il ne reste plus de descripteurs ouverts.

Ajoutés : pour gérer les sessions, utilisez les préfixes Local\ et Global\ du nom de l'événement (ou du mutex). Si votre application est utilisateur par utilisateur, ajoutez simplement un nom d'utilisateur connecté mutilé de manière appropriée au nom de l'événement.

43voto

JaredPar Points 333733

En général oui cela fonctionnera. Cependant, le diable est dans les détails.

Tout d'abord, vous voulez Fermer le mutex dans une enfin. Sinon votre processus pourrait se terminer brusquement et le laisser dans un signalé état (pensez à une exception). Qu'allait-il faire en sorte que les futures instances de processus ne serait pas en mesure de démarrer.

Malheureusement, même avec un bloc finally vous devez traiter avec le potentiel qu'un processus sera terminé sans libérer le mutex. Cela peut arriver par exemple si un utilisateur supprime le processus via le gestionnaire des tâches. Il est une condition de concurrence dans votre code, ce qui permettrait une deuxième processus pour obtenir un AbandonedMutexException dans le WaitOne appel. Vous aurez besoin d'un programme de rétablissement pour cette.

Je vous encourage à lire sur les détails de la classe Mutex. L'aide il n'est pas toujours simple

http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx

MODIFIER l'Expansion de la race condition de possibilité

La séquence suivante d'événements peuvent se produire qui serait la cause d'une deuxième instance de l'application à lancer.

  1. Procédure Normale De Démarrage
  2. Deuxième Processus démarre et acquiert une poignée pour le mutex, mais est mis à l'écart avant la WaitOne appel
  3. Processus n ° 1 est brusquement interrompu. Le Mutex n'est pas détruit parce que le processus 2 a une poignée. C'est plutôt à un état d'abandon
  4. Deuxième processus commence à courir à nouveau et obtient un AbanonedMutexException

12voto

Stefan Points 29091

Vous pouvez utiliser un mutex, mais assurez-vous d'abord que c'est vraiment ce que vous voulez.

Parce que "en évitant de multiples instances" n'est pas clairement défini. Il peut signifier

  1. En évitant de multiples instances commencé dans la même session de l'utilisateur, peu importe le nombre de postes de travail que la session utilisateur a, mais permettant à de multiples instances de l'exécution simultanée de plusieurs sessions d'utilisateur.
  2. En évitant de multiples instances commencé dans le même bureau, mais en permettant à de multiples instances d'exécuter en tant que chacun est dans un bureau séparé.
  3. En évitant de multiples instances commencé pour le même compte d'utilisateur, peu importe le nombre d'ordinateurs de bureau ou des sessions en cours d'exécution en vertu de ce compte existe, mais en permettant à de multiples instances d'exécuter simultanément pour les sessions exécute sous un compte d'utilisateur différent.
  4. En évitant de multiples instances commencé sur la même machine. Cela signifie que peu importe combien de postes de travail sont utilisés par un nombre arbitraire d'utilisateurs, il peut y avoir au plus une occurrence de programme en cours d'exécution.

À l'aide d'un mutex, vous êtes essentiellement en utilisant le définir le nombre 4.

3voto

Michael Burr Points 181287

Sur Windows, l'arrêt d'un processus a les résultats suivants:

  • Toutes les autres threads du processus sont marqués pour la résiliation.
  • Des ressources allouées par le processus sont libérés.
  • Tous les objets de noyau sont fermés.
  • Le processus de code est supprimé de la mémoire.
  • Le code de sortie du processus est défini.
  • L'objet de processus est signalé.

Mutex les objets sont les objets de noyau, de sorte que tout détenu par un processus sont fermés lorsque le processus se termine (sous Windows en tout cas).

Mais, note le bit suivant de la CreateMutex() docs:

Si vous utilisez un mutex nommé à la limite de votre application à un seul exemple, un utilisateur malveillant peut créer ce mutex avant de le faire et de prévenir de votre demande de départ.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X