Есть ли в C # операция «попытаться заблокировать, пропустить, если истекло время ожидания»? - PullRequest
53 голосов
/ 12 августа 2008

Мне нужно попытаться заблокировать объект, и если он уже заблокирован, просто продолжить (после истечения времени ожидания или без него).

Оператор блокировки C # блокирует.

Ответы [ 5 ]

87 голосов
/ 12 августа 2008

Эд имеет правильную функцию для вас. Только не забудьте позвонить Monitor.Exit(). Вы должны использовать блок try-finally, чтобы гарантировать правильную очистку.

if (Monitor.TryEnter(someObject))
{
    try
    {
        // use object
    }
    finally
    {
        Monitor.Exit(someObject);
    }
}
37 голосов
/ 12 августа 2008

Я считаю, что вы можете использовать Monitor.TryEnter().

Оператор блокировки просто переводит вызов Monitor.Enter() и блок try catch.

11 голосов
/ 19 мая 2014

У меня была та же проблема, я закончил тем, что создал класс TryLock, который реализует IDisposable, а затем использовал оператор using для управления областью блокировки:

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;
        }
    }
}

А затем используйте следующий синтаксис для блокировки:

var obj = new object();

using (var tryLock = new TryLock(obj))
{
    if (tryLock.HasLock)
    {
        Console.WriteLine("Lock acquired..");
    }
}
3 голосов
/ 12 августа 2008

Вероятно, вы сами это выясните сейчас, когда другие указали вам правильное направление, но TryEnter также может принять параметр тайм-аута.

Книга Джеффа Рихтера "CLR Via C #" - превосходная книга о деталях внутренних органов CLR, если вы попадаете в более сложные вещи.

2 голосов
/ 03 февраля 2017

Рассмотрите возможность использования AutoResetEvent и его метода WaitOne с таймаутом ввода.

static AutoResetEvent autoEvent = new AutoResetEvent(true);
if(autoEvent.WaitOne(0))
{
    //start critical section
    Console.WriteLine("no other thread here, do your job");
    Thread.Sleep(5000);
    //end critical section
    autoEvent.Set();
}
else
{
    Console.WriteLine("A thread working already at this time.");
}

См. https://msdn.microsoft.com/en-us/library/cc189907(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v=vs.110).aspx и https://msdn.microsoft.com/en-us/library/cc190477(v=vs.110).aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...