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

时间:2008-08-12 06:19:39

标签: c# multithreading locking

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

C#lock语句阻塞。

5 个答案:

答案 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).aspxhttps://msdn.microsoft.com/en-us/library/cc190477(v=vs.110).aspx