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

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

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

12.08.2008 06:19:38
5 ОТВЕТОВ
РЕШЕНИЕ

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

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

40
22.01.2013 10:25:53
Что если я имею дело с межпроцессным параллелизмом? Есть ли способ использовать Mutex подобным образом?
Mihai Todor 26.03.2014 10:02:23
Это не будет работать, если вы используете метод async stackoverflow.com/questions/21404144/…
Noam 16.08.2019 03:55:51

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

if (Monitor.TryEnter(someObject))
{
    try
    {
        // use object
    }
    finally
    {
        Monitor.Exit(someObject);
    }
}
99
12.08.2008 06:37:34
+1, спасибо! Предлагаем небольшое изменение, если хотите, просто чтобы напомнить, что (почти) всегда можно использовать расширенные конструкции / шаблоны без вложения фигурных скобок на неопределенный срок.
ceztko 1.07.2011 19:07:48
@ceztko, можешь уточнить? Как правило, для освобождения N ресурсов, например, в C #, требуется N вложенных блоков try-finally. Использование оператора помогает избежать этого только для IDisposables. Пропуск блоков try-finally может привести к утечке ресурсов в случае исключения. Например, документация Monitor разъясняет, что блок finally необходим. Странно, ссылка Эда пренебрегает этим.
Derek Park 5.07.2011 21:51:46

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

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

3
12.08.2008 07:54:39

У меня была та же проблема, я закончил тем, что создал класс, 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..");
    }
}
16
19.05.2014 00:22:30

Рассмотрите возможность использования 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

3
11.06.2018 11:40:29
Если millisecondsTimeout равен нулю, метод не блокируется. Он проверяет состояние дескриптора ожидания и немедленно возвращается. Этот работает для меня и, вероятно, является лучшим ответом. Я редактирую, чтобы дать готовое решение.
vezenkov 11.06.2018 10:10:23