Monitor
выполняет эту работу за вас, но блокировка в потоке (и, следовательно, открыта для рекурсивных вызовов!). В операторе lock
также используется Monitor
(используется метод блокировки Enter
), но вместо этого вы можете работать с методом TryEnter
:
if(Monitor.TryEnter(myLockObject))
{
try
{
DoSomething(); // main code
}
finally
{
Monitor.Exit(myLockObject);
}
}
TryEnter не блокирует, но возвращает bool
, указывающий, была ли блокировка успешно получена или нет.
Если вы хотите, чтобы рекурсивные вызовы не вводили блок основного кода снова, вы должны использовать вместо этого семафор. Семафоры используют счетчики вместо блокировки объектов, поэтому вы не можете повторно войти даже из одного потока:
class Program
{
private static Semaphore sem = new Semaphore(1, 1);
static void Main(string[] args)
{
MyMethod();
MyMethod();
}
private static void MyMethod()
{
if(sem.WaitOne(0))
{
try
{
Console.WriteLine("Entered.");
MyMethod(); // recursive calls won't re-enter
}
finally
{
sem.Release();
}
}
else
{
Console.WriteLine("Not entered.");
}
}
}