2009-08-19 8 views
45

Est-il possible de déterminer si un objet est verrouillé en C#? J'ai la position peu enviable, à travers le design où je lis depuis une file d'attente dans une classe, et j'ai besoin de vider le contenu dans une collection dans la classe. Mais cette collection est également en lecture/écriture à partir d'une interface en dehors de la classe. Donc, évidemment, il peut y avoir un cas où la collection est en cours d'écriture, en même temps que je veux écrire à elle.Existe-t-il un moyen de détecter si un objet est verrouillé?

Je pourrais programmer autour d'elle, dites using le délégué mais ce serait moche.

+0

Yea, Merci à tous. Cela confirme à peu près ce que je pensais déjà. –

Répondre

40

Vous pouvez toujours appeler le TryEnter method statique sur le Monitor class en utilisant la valeur 0 pour attendre la valeur. Si elle est verrouillée, l'appel retournera faux. Toutefois, le problème ici est que vous devez vous assurer que la liste à laquelle vous essayez de synchroniser l'accès est verrouillée sur elle-même afin de synchroniser l'accès.

Il est généralement mal vu d'utiliser l'objet dont l'accès est en cours de synchronisation comme objet à verrouiller (exposant trop de détails internes d'un objet). Rappelez-vous, le verrou peut être sur n'importe quoi d'autre, donc l'appeler sur cette liste est inutile à moins que vous soyez sûr que cette liste est ce qui est verrouillé.

10

Monitor.TryEnter réussira si l'objet n'est pas verrouillé, et retournera faux si à ce moment même, l'objet est verrouillé. Cependant, notez qu'il y a une race implicite ici: l'instance retournée par cette méthode, l'objet ne peut plus être verrouillé.

6

Actuellement, vous pouvez appeler Monitor.TryEnter pour vérifier si l'objet est verrouillé ou non.

Dans .NET 4.0 équipe CLR va ajouter "API d'inspection Lock"

Voici une citation de Rick Byers article:

inspection de verrouillage
Nous ajoutons des API simples à ICorDebug qui vous permet d'explorer les verrous gérés (Moniteurs). Par exemple, si un thread est bloqué en attente d'un verrou, vous pouvez trouver quel autre thread détient actuellement le verrou (et s'il y a un time-out).

Alors, avec cette API, vous serez en mesure de vérifier:
1) Quel objet tient une serrure?
2) Qui l'attend?

Espérons que cela aide.

+0

Intéressant. Bob. –

7

Je ne suis pas sûr si un appel statique à TryEnter avec un temps de 0 garantira que le verrou ne sera pas acquis s'il est disponible. La solution que je l'ai fait pour tester en mode débogage que la variable de synchronisation a été bloquée à l'aide a été la suivante:

#if DEBUG 
// Make sure we're inside a lock of the SyncRoot by trying to lock it. 
// If we're able to lock it, that means that it wasn't locked in the first 
// place. Afterwards, we release the lock if we had obtained it. 
bool acquired = false; 
try 
{ 
    acquired = Monitor.TryEnter(SyncRoot); 
} 
finally 
{ 
    if (acquired) 
    { 
     Monitor.Exit(SyncRoot); 
    } 
} 
Debug.Assert(acquired == false, "The SyncRoot is not locked."); 
#endif 
+2

La variable 'isNotLocked' est plutôt mal nommée. Vous débloquez si 'isNotLocked' est vrai - alors que techniquement c'est correct car' isNotLocked' sera vrai quand le verrou a été acquis avec succès le code ci-dessus est vraiment mauvais à lire. Si quelqu'un d'autre doit travailler dessus, il aura un moment WTF. – ChrisWue

+2

Ne fonctionne pas si le thread sur lequel il s'exécute est le même thread qui possède le verrou. On dira que le verrou est libre alors qu'en réalité ce n'est pas le cas. –

Questions connexes