2008-08-12 10 views

Répondre

34

Je crois que vous pouvez utiliser Monitor.TryEnter().

L'instruction lock se traduit simplement par un appel Monitor.Enter() et un bloc try catch.

+0

si je fais face à la concurrence inter-processus? Existe-t-il un moyen d'utiliser un Mutex de la même manière? –

80

Ed a la bonne fonction pour vous. N'oubliez pas d'appeler le Monitor.Exit(). Vous devez utiliser un bloc try-finally pour garantir un nettoyage correct.

if (Monitor.TryEnter(someObject)) 
{ 
    try 
    { 
     // use object 
    } 
    finally 
    { 
     Monitor.Exit(someObject); 
    } 
} 
+0

+1, merci! Proposé un petit changement, si vous voulez, juste pour rappeler qu'il est (presque) toujours possible d'utiliser des constructions/modèles avancés sans imbriquer indéfiniment des accolades. – ceztko

+0

@ceztko, pouvez-vous clarifier? En général, la libération de ressources N dans, par exemple, C# nécessite N blocs try-finally imbriqués. L'instruction using permet d'éviter cela uniquement pour IDisposables. Ignorer les blocs try-finally peut entraîner des fuites de ressources en cas d'exception. Par exemple, la documentation [Monitor] (http://msdn.microsoft.com/en-us/library/aa720302 (v = VS.71) .aspx) précise que le bloc finally est nécessaire. Bizarrement, le lien d'Ed néglige cela. –

3

Vous trouverez probablement ceci pour vous-même maintenant que les autres vous ont fait dans la bonne direction, mais TryEnter pouvez également prendre un paramètre de délai d'attente.

Le "CLR Via C#" de Jeff Richter est un excellent livre sur les détails des entrailles CLR si vous vous lancez dans des choses plus compliquées.

10

J'ai eu le même problème, je fini par créer une classe TryLock qui implémente IDisposable et utilise ensuite la déclaration using pour contrôler la portée de la serrure:

public class TryLock : IDisposable 
{ 
    private object locked; 

    public bool HasLock { get; private set; } 

    public TryLock(object obj) 
    { 
     if (Monitor.TryEnter(obj)) 
     { 
      HasLock = true; 
      locked = obj; 
     } 
    } 

    public void Dispose() 
    { 
     if (HasLock) 
     { 
      Monitor.Exit(locked); 
      locked = null; 
      HasLock = false; 
     } 
    } 
} 

Et puis utilisez la syntaxe suivante pour verrouiller:

var obj = new object(); 

using (var tryLock = new TryLock(obj)) 
{ 
    if (tryLock.HasLock) 
    { 
     Console.WriteLine("Lock acquired.."); 
    } 
}