Should I use ManualResetEvent as a lock object?

The method below should return true for the first call and false for any other call.

Are there any problems with this? Is it safe to use the reset event to lock?

private ManualResetEvent _resetEvent = new ManualResetEvent(false); public bool AmIFirst() { lock (_resetEvent) { bool first = !_resetEvent.WaitOne(0); if (first) _resetEvent.Set(); return first; } } 

Edit: I made some changes after viewing the comments. I am stuck on ManualResetEvent due to a previous design idea. I don’t need it at all.

 class ActionSynchronizer { private Timer _expirationTimer; private object _locker = new object(); private bool _executionRequired = true; private SomeDelegate _onExpired = delegate { }; public ActionSynchronizer(SomeDelegate onExpired) { _onExpired = onExpired; expirationTimer = new Timer(OnExpired, null, 30000, Timeout.Infinite); } public bool IsExecutionRequired() { if (!_executionRequired) return false; lock (_locker) { if (_executionRequired) { _executionRequired = false; return true; } return false; } } private void OnExpired(object state) { if (_executionRequired) { lock (_locker) { if (_executionRequired) { _executionRequired = false; // http://stackoverflow.com/questions/1712741/why-does-asynchronous-delegate-method-require-calling-endinvoke/1712747#1712747 _onExpired.BeginInvoke(_originalAction, EndInvoke, null); } } } } } // ... { if (_action.Sync.IsExecutionRequired()) _action.Invoke(); } 
+4
source share
4 answers

I would go the other way here ...

 private int counter; ... if(Interlocked.Increment(ref counter) == 1) { // yes, I'm first } 

Ceiling protection, no locks. Or if you are worried about wrapping Int32:

 if(Interlocked.CompareExchange(ref counter, 1, 0) == 0) { // yes, I'm first } 
+13
source

Currently, I only lock () only for a simple System.Object that I created to lock with.

I would definitely not lock () on something like an event, and not because it would not work, but because I think it is potentially rather confusing to use lock () for an object that it is itself (although completely separate), associated with operations such as kernel locking.

I don’t understand what you are actually doing here, but it looks more like something that could improve the named Mutex.

+2
source

I think it is better to use lock () for this on an object.

In addition, you can prevent excessive blocking of the stream by using the “double block check”

eg.

 private object _protection = new object(); private bool _firstTime = true; public bool AmIFirst() { if (!_firstTime) return false; lock (_protection) { if (!_firstTime) return false; _firstTime = false; return true; } } 

Note ... - there are interesting comments on double blocking checking - Double blocking checking in .NET - I'm still reading about it!


One more note ... it's not clear from the code snippet you posted, but if you want to implement a global singleton, then solution 4 at http://www.yoda.arachsys.com/csharp/singleton.html is a good place for launch

+1
source

The only thing you need to do is make sure that the same object that you are blocking is available to all instances of code that requires synchronization. Other than that, no problem.

0
source

Source: https://habr.com/ru/post/1344572/


All Articles