10
votes

.NET Mutex sur la plate-forme Windows: qu'est-ce qui leur arrive après avoir fini?

J'ai un simple programme .NET, qui vérifie si un autre instance a été démarré:

    Mutex mutex = new Mutex(false,"MyMutexName");
    if (!mutex.WaitOne(1))
        return;

    try{
    //do stuff
    }
    catch{ //exceptions}
    finally
    {
        mutex.ReleaseMutex();
    }


3 commentaires

Les mutex nommés ne sont normalement utilisés que pour la coordination de la communication croisée, ce qui n'est pas ce que votre exemple apparaît du tout.


@Steven: Utiliser des mutiles pour cela est une très bonne utilisation. Bien mieux que d'essayer de détecter une fenêtre précédente ou un nom de processus ou quelque chose.


J'ai mis à jour ma question, car vous faites deux choses semi-liées dans votre code: 1) Utilisation d'un Mutex nommé pour détecter l'existence d'une instance précédente de votre demande 2) Synchronisation entre les processus avec ce mutex.


3 Réponses :


3
votes

Les mutex sont des poignées au niveau du système d'exploitation. Ils seront fermés lorsque votre processus le fait (si vous ne les fermez pas plus tôt, c'est-à-dire.)

éditer

OK, j'ai clairement mal compris l'exemple et la question. Si vous essayez simplement de détecter si un autre instance existe, vous créeriez un mutex nommé (ou un objet similaire) et simplement vérifier son existence sans jamais le verrouiller.

L'appel à watile verrouille dessus, en prenant de la propriété, tandis que releasemutex s'en débarrasse (tant qu'il n'y a pas d'appels supplémentaires à Service d'attente ). Si vous mettez fin au fil sans libérer complètement le mutex, il quitte l'objet dans un mauvais état, comme expliqué dans les citations de texte MiMAH.

J'ai pris votre question comme si vous fermez le manche avant la fin du processus, ce qui est une autre chose entièrement.

additionnel

au niveau SDK [API] [1], vous pouvez appeler Createmutex avec l'attente d'échec lorsqu'un mutex du même nom a déjà été créé. En .NET (Eh bien, en 4.0, au moins), il y a un [constructeur] [2] qui remplit un crééNew bool.

[1]: http: // msdn. Microsoft.com/en-us/Library/MS682411(vs.85).aspx Createmutex

[2]: http: // msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx mutex


0 commentaires

3
votes

de MSDN

Si un fil se termine tout en possédant un mutex, le mutex est dit être abandonné. L'état du mutex est défini sur signalé et la prochaine attente Le fil est propriétaire. Si personne ne possède Le mutex, l'état du mutex est signalé. À partir de la version 2.0 de le .NET Framework, un AbandonedmutexException est jeté dans le prochain fil qui acquiert le mutex. Avant la version 2.0 du .NET framework, aucune exception n'a été jeté.

prudence

Un mutex abandonné indique souvent un erreur grave dans le code. Lorsqu'un Fil se décolle sans libérer le mutex, les structures de données protégées par le mutex pourrait ne pas être dans un état cohérent. Le prochain thread à Demander la propriété du mutex peut gérer cette exception et procéder, si l'intégrité des structures de données peut être vérifié.

Dans le cas d'un mutex à l'échelle du système, un Mutex abandonné pourrait indiquer qu'un L'application a été terminée brusquement (par exemple, en utilisant Gestionnaire de tâches Windows).


1 commentaires

Pour clarifier, ce qui rend un mutex "système à l'échelle" est que plusieurs processus y ont une poignée. Sinon, lorsque le processus ferme, il faut le mutex avec celui-ci.



12
votes

Il s'agit d'un mutex nommé, il est donc visible et peut être ouvert dans d'autres processus. Windows utilise un simple nombre de références sur la poignée. Si vous ne disposez pas (), il vous convient explicitement, le finaliseur fermera la poignée pour vous. Si votre programme bombe est dur et n'exécute jamais le finaliseur, Windows le fera quand il nettoie les ressources utilisées par votre programme.

qui décrira automatiquement le nombre de références. Si cela compte jusqu'à zéro (aucun autre processus ne dispose d'une poignée ouverte dessus), l'objet du noyau est libéré. ​​

En d'autres termes: vous n'avez pas de problème, peu importe la façon dont les choses se révèlent. L'objet mutant réel vit dans le pool de mémoire du noyau. Vous pouvez le voir avec l'outil Winobj Sysinternals.


2 commentaires

Juste, c'est ce que j'ai dit initialement sur la poignée elle-même. La complication est que, si un autre processus reçoit une poignée à votre nommé Mutex, puis vous fermez un fil après avoir acquis la propriété, le mutex est abandonné. Voir ma réponse pour plus de détails.


Aussi, mutex.Dispose () ne le libère pas. Besoin d'appeler Releasemutex () explicitement, sinon le nouveau propriétaire recevra AbandonedmutexException.