Comment trouver ce Mutex en C# est acquis?
Comment puis-je trouver de mutex poignée en C# qu'un mutex est acquis?
Quand mutex.WaitOne(timeout)
les délais d'attente, il retourne false
. Cependant, comment puis-je trouver qu'à partir du handle de mutex? (Peut-être à l'aide de p/invoke.)
Mise à JOUR:
public class InterProcessLock : IDisposable
{
readonly Mutex mutex;
public bool IsAcquired { get; private set; }
public InterProcessLock(string name, TimeSpan timeout)
{
bool created;
var security = new MutexSecurity();
security.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
mutex = new Mutex(false, name, out created, security);
IsAcquired = mutex.WaitOne(timeout);
}
#region IDisposable Members
public void Dispose()
{
if (IsAcquired)
{
mutex.ReleaseMutex();
IsAcquired = false;
}
}
#endregion
}
Actuellement, je suis en utilisant ma propre propriété IsAcquired
afin de déterminer si je dois libérer un mutex. Pas indispensable, mais plus claire, serait de ne pas utiliser une copie secondaire de l'information représentée par IsAcquired
de propriété, mais plutôt de demander directement le mutex s'il est acquis par moi. Depuis l'appel de mutex.ReleaseMutex()
lève une exception si il n'est pas acquis par moi.
(Par acquis état, je veux dire que le mutex est dans pas signalé état quand je suis posséder le mutex.)
(EDIT: j'ai ajouté IsAcquired = false;
grâce à mattdekrey post.)
Vous devez vous connecter pour publier un commentaire.
Comme vous le constaté, il n'y a pas de représentants du public sur
Mutex
classe:http://msdn.microsoft.com/en-us/library/system.threading.mutex_members.aspx
Il n'y a également pas de fonctions natives pour que:
http://msdn.microsoft.com/en-us/library/ms686360%28v=VS.85%29.aspx
Cependant, il y a quelques sans-papiers/fonctions non prises en charge en particulier dans
ntdll.dll
. Ils permettent d'accéder aux objets du système. Cependant, ces fonctions peuvent changer ou ne pas être disponibles dans les futures versions de système d'exploitation.Donc, la réponse est: Il n'est pas possible à l'aide de moyens conventionnels.
La raison, il n'est pas propre façon de le faire c'est parce qu'il n'est pas une bonne idée et la raison est parce que les conditions de course sont-très - facile à présenter lorsque vous comptez sur ce type de logique. Si vos besoins de conception de changer.
Tout d'abord, vous ne devez pas acquérir un verrou dans un constructeur. Tourner cette classe dans une usine qui renvoie un initialisé correctement objet mutex. De cette façon, vous pouvez savoir si vous avez acquis le verrouiller ou pas.
NE comptez PAS sur d'en Disposer à libérer les verrous, cette demande de blocage monté code qui est difficile à maintenir. Utiliser un try/finally bloc pour s'assurer qu'il est libéré.
Délais d'attente sont un peu louche. Utilisez uniquement des délais d'attente lorsqu'il n'est pas l'acquisition du verrou peut être considérée comme normale de fonctionnement. Ne pas être en mesure d'acquérir le verrou est généralement un bug et simplement de l'éviter avec des délais d'attente cache le bogue. Si vous avez besoin de délais d'attente, pensez à utiliser un événement (peut-être AutoResetEvent), ce qui peut être plus approprié.
Release()
méthode qui vous permettra d'appelerDispose()
, qu'il sera ok? Ensuite, comment puis-je utiliserAutoResetEvent
de synchroniser les processus?Release
ouDispose
est simple. Ou quelle complication-vous y voir? 2, les Ruisseaux/Fichiers ne peuvent pas acquérir des verrous dans un constructeur. Non, mais ils sont l'allocation d'un système de poignée et. Quelle est la différence entre le verrouillage d'un fichier et de verrouiller un mutex? 3, la direction est beaucoup plus facile à déboguer et à entretenir. je ne peux pas être plus d'accord:) Centralisée par rapport à des systèmes distribués...object obj, ref bool lockTaken
surcharge deMonitor.Enter
). J'avais suggérons fortement d'utiliser unlock()
bloc au lieu de cela, et si ce n'est pas possible, unusing()
bloc avec un objet d'assistance qui déverrouille dans sonDispose
méthode. De cette façon, vous n'avez zéro (lock) ou un lieu (Défaire) où vous devez écrire le bon verrouillage/déverrouillage du code.Bien, ce n'est pas exactement ce que vous demandez, mais je pense que cela permettrait de résoudre votre problème: pourquoi ne pas simplement ajouter une gestion d'erreur spécifiquement pour l'exception qui se produit si le Mutex est acquis par quelqu'un d'autre?
Pourquoi ne pouvez-vous pas utiliser
Mutex.OpenExisting
MODIFIER
Je devine que certains de cela.
Il semble que vous essayez de développer une API. L'un des articles que vous offrez dans votre API est une InterProcessLock.
Je vais supposer que vous êtes le partage d'une collection sur les threads et que vous utilisez le Mutex à assurez-vous qu'une opération sur un temps.
Je voudrais revenir sur cette conception. Que faire si je n'ai jamais wraped
InterProcessLock myLock = new InterProcessLock("LockMutex", TimeSpan.FromMilliseconds(100.0))
en aide? Jeter ne serait pas appelé. Que faire si l'utilisateur n'appelle jamais les Jeter à tous?Il n'y aurait abandonné Mutex
De MSDN
Si vous essayez de protéger vos utilisateurs, vous pouvez vouloir les aider en contrôlant le Mutex pour eux afin qu'ils aient jamais à vous inquiéter à ce sujet.
Un exemple possible est
C'est une façon possible. Tout dépend de ce que le but est. Je ne voudrais PAS de relais sur l'utilisateur final à l'appel d'un Jeter depuis un Mutex est un système d'exploitation de construire. Et si le nom n'est pas unquie il pourrait en effet d'autres processus, en utilisant le même nom de mutex.
IDisposable.Dispose
ou personnaliséRelease method
.Cela ne profite pas à l'affiche originale de la question, mais ici il va.
Bien que je ne suis pas en désaccord avec d'autres posters sur la bonne utilisation de Mutex, j'ai eu une demande d'où j'avais besoin de tester si quelqu'un possède un mutex sans prendre possession de moi-même. Comme mentionné par d'autres, le seul moyen est d'utiliser un sans-papiers NtQueryMutant système d'appel de ntdll.dll. J'ai créé une méthode d'extension pour la classe Mutex qui peut être utilisée comme ceci:
Et ici est la mise en œuvre
GC.KeepAlive
appel. Mieux encore serait de simplement déclarerNtQueryMutant
d'utiliser unSafeWaitHandle
paramètre..NET classe Mutex est originaire mutex wrapper, qui donne les mêmes possibilités, en tant que natif de mutex de l'API (à l'exception d'attente pour le nombre de waitable objets de type différent). Si vous souhaitez acquérir des mutex sans blocage, appel mutex.WaitOne(0). À l'aide de PInvoke, vous pouvez appeler WaitForSingleObject, avec le même résultat.
Si vous êtes vraiment essayer de faire un inter-processus de verrouillage, comme son nom l'indique, vous voulez un moyen de détecter si le Mutex a été effectivement acquis de toute façon, c'est exact? Je ne suis pas sûr de savoir comment votre code qui utilise votre
InterProcessLock
serait assurée d'être verrouillé si il n'y avait pasIsAcquired
de la propriété. (Aussi, pour se protéger contre les programmeurs qui, par erreur, appelez dispose deux fois, j'avais mis leIsAcquired
àfalse
dans votreDispose
méthode.)J'ai mis en place la même chose moi-même (parce que je préfère de beaucoup l'aide du bloc d'essayer, enfin, il suffit de libérer le mutex) et au lieu de cela a déclenché une exception lorsque le délai a été dépassé, ce qui, si je me souviens le projet correctement, ne pas appeler la méthode dispose.
Edit:
Avantage de jeter l'exception dans le constructeur: votre section critique est également complètement évités, et vous pouvez effectuer la gestion d'erreur dans les
catch
bloc, ce qui pourrait inclure le même appel de la méthode de votre section critique avait, de toute façon, même si personnellement, je considère qu'une mauvaise pratique.À la réflexion, plutôt que d'utiliser
try ... catch
comme indiqué dans une autre réponse, vous pouvez utiliser les éléments suivants sur votre disposer:Il se sent un peu ironique de
lock
un mutex, mais là vous l'avez. Alors que je suis totalement d'accord que vous ne devriez pas compter sur de Disposer d'être appelé en raison de la documentation de l'interface IDisposable, je pense qu'il est très pratique d'avoir un inter-processus en section critique indiquée par unusing() { }
bloc.Dispose()
deux fois, il va lever une exception. Donc, ils peuvent trouver qu'il ya un bug dans leur code. Plus tôt, j'étais aussi de lancer une exception dans le constructeur. Mais plus tard, j'ai changé, depuis les programmeurs peuvent décider, dans certaines situations, pour exécuter le code, même si la serrure n'est pas acquis. (Par exemple, il y a des processus indépendants et peut-être l'un est resté coincé, donc, la deuxième est en attente et alors, il sera exécuté en dépit de cela.)