在 C # 中是否有“尝试锁定,如果超时则跳过”操作?

我需要尝试锁定一个对象,如果它已经锁定只是继续(超时后,或没有它)。

C # lock 语句被阻塞。

30975 次浏览

我相信你可以使用 Monitor.TryEnter()

Lock 语句仅转换为 Monitor.Enter()调用和 try catch块。

Ed 给你找了个合适的职位。别忘了打电话给 Monitor.Exit()。您应该使用 try-finally块来保证正确的清理。

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

现在其他人已经为您指明了正确的方向,您可能会自己发现这一点,但是 TryEnter 也可以采用超时参数。

Jeff Richter 的“ CLR Via C #”是一本关于 CLR 内部细节的优秀书籍,如果你正在进入更复杂的东西。

我遇到了同样的问题,最终创建了一个实现 IDisposable 的类 TryLock,然后使用 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..");
}
}

考虑使用 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.");
}

请参见“ http://msdn.microsoft.com/en-us/library/cc189907(v = vs. 110) . aspx”rel = “ nofollow noReferrer”> 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

基于 德里克斯接电话的一个小帮手方法:

private bool TryExecuteLocked(object lockObject, Action action)
{
if (!Monitor.TryEnter(lockObject))
return false;


try
{
action();
}
finally
{
Monitor.Exit(lockObject);
}


return true;
}

用法:

private object _myLockObject;
private void Usage()
{
if (TryExecuteLocked(_myLockObject, ()=> DoCoolStuff()))
{
Console.WriteLine("Hurray!");
}
}