Is there a “try to lock, skip if timed out” operation in C#?

前端 未结 5 1568
执念已碎
执念已碎 2020-12-23 11:17

I need to try to lock on an object, and if its already locked just continue (after time out, or without it).

The C# lock statement is blocking.

相关标签:
5条回答
  • 2020-12-23 11:47

    Consider using AutoResetEvent and its method WaitOne with a timeout input.

    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.");
    }
    

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

    0 讨论(0)
  • 2020-12-23 11:49

    I believe that you can use Monitor.TryEnter().

    The lock statement just translates to a Monitor.Enter() call and a try catch block.

    0 讨论(0)
  • 2020-12-23 11:51

    Ed's got the right function for you. Just don't forget to call Monitor.Exit(). You should use a try-finally block to guarantee proper cleanup.

    if (Monitor.TryEnter(someObject))
    {
        try
        {
            // use object
        }
        finally
        {
            Monitor.Exit(someObject);
        }
    }
    
    0 讨论(0)
  • 2020-12-23 11:53

    I had the same problem, I ended up creating a class TryLock that implements IDisposable and then uses the using statement to control the scope of the lock:

    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;
            }
        }
    }
    

    And then use the following syntax to lock:

    var obj = new object();
    
    using (var tryLock = new TryLock(obj))
    {
        if (tryLock.HasLock)
        {
            Console.WriteLine("Lock acquired..");
        }
    }
    
    0 讨论(0)
  • 2020-12-23 12:00

    You'll probably find this out for yourself now that the others have pointed you in the right direction, but TryEnter can also take a timeout parameter.

    Jeff Richter's "CLR Via C#" is an excellent book on details of CLR innards if you're getting into more complicated stuff.

    0 讨论(0)
提交回复
热议问题