Есть ли в C# операция «попробуй заблокировать, пропустить, если истекло время ожидания»?
-
08-06-2019 - |
Вопрос
Мне нужно попытаться заблокировать объект, и если он уже заблокирован, просто продолжить (по истечении времени или без него).
Оператор блокировки C# блокирует.
Решение
Я считаю, что вы можете использовать Monitor.TryEnter()
.
Оператор блокировки просто преобразуется в Monitor.Enter()
звонок и try catch
блокировать.
Другие советы
У Эда есть подходящая для вас функция.Только не забудь позвонить Monitor.Exit()
.Вам следует использовать try-finally
блокируйте, чтобы гарантировать правильную очистку.
if (Monitor.TryEnter(someObject))
{
try
{
// use object
}
finally
{
Monitor.Exit(someObject);
}
}
У меня была та же проблема, в итоге я создал класс 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..");
}
}
Вероятно, вы сами это поймете теперь, когда другие указали вам правильное направление, но TryEnter также может принимать параметр таймаута.
Книга Джеффа Рихтера «CLR Via C#» — отличная книга о деталях внутреннего устройства CLR, если вы занимаетесь более сложными вещами.
Рассмотрите возможность использования 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