我需要尝试锁定一个对象,如果它已经锁定只是继续(超时或没有它)。
C#lock语句阻塞。
答案 0 :(得分:87)
Ed为您提供了正确的功能。别忘了给Monitor.Exit()
打个电话。您应该使用try-finally
块来保证正确清理。
if (Monitor.TryEnter(someObject))
{
try
{
// use object
}
finally
{
Monitor.Exit(someObject);
}
}
答案 1 :(得分:37)
我相信你可以使用Monitor.TryEnter()
。
锁定语句只会转换为Monitor.Enter()
来电和try catch
阻止。
答案 2 :(得分:11)
我遇到了同样的问题,我最终创建了一个实现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..");
}
}
答案 3 :(得分:3)
你可能会发现这一点,因为其他人已经指出了你正确的方向,但TryEnter也可以采取超时参数。
Jeff Richter的“CLR Via C#”是一本关于CLR内部细节的优秀书籍,如果你遇到更复杂的东西。
答案 4 :(得分:2)
考虑使用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