【发布时间】:2008-08-12 06:19:38
【问题描述】:
我需要尝试锁定一个对象,如果它已经锁定就继续(在超时之后,或者没有它)。
C# lock 语句被阻塞。
【问题讨论】:
标签: c# multithreading locking
我需要尝试锁定一个对象,如果它已经锁定就继续(在超时之后,或者没有它)。
C# lock 语句被阻塞。
【问题讨论】:
标签: c# multithreading locking
Ed 为您提供了正确的功能。只是不要忘记致电Monitor.Exit()。您应该使用try-finally 块来保证正确清理。
if (Monitor.TryEnter(someObject))
{
try
{
// use object
}
finally
{
Monitor.Exit(someObject);
}
}
【讨论】:
我相信你可以使用Monitor.TryEnter()。
lock 语句只转换为Monitor.Enter() 调用和try catch 块。
【讨论】:
我遇到了同样的问题,我最终创建了一个实现 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..");
}
}
【讨论】:
obj 实例只是一个如何使用 TryLock 类锁定任何对象的示例。显然,没有必要在线程之间以某种方式共享的对象(即静态实例或单例)进行锁定 - 所以你是对的,我们通常不会初始化局部变量对象实例并锁定它。
考虑使用带有超时输入的 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
【讨论】:
既然其他人已经为您指出了正确的方向,您可能会自己发现这一点,但 TryEnter 也可以采用超时参数。
Jeff Richter 的“CLR Via C#”是一本关于 CLR 内部细节的优秀书籍,如果您正在研究更复杂的东西。
【讨论】: