我应该使用 ManualResetEvent 作为锁定对象吗?
下面的方法对于第一次调用应返回 true,对于任何其他调用应返回 false。
是不是有什么问题呢?使用重置事件进行锁定安全吗?
private ManualResetEvent _resetEvent = new ManualResetEvent(false);
public bool AmIFirst()
{
lock (_resetEvent)
{
bool first = !_resetEvent.WaitOne(0);
if (first)
_resetEvent.Set();
return first;
}
}
编辑:在查看您的评论后,我做了一些更改。由于以前的设计理念,我被困在 ManualResetEvent
上。我其实根本不需要它。
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();
}
The method below should return true for the first call, and false for any other call.
Is there any problem with it? Is it safe to use the reset event for locking?
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 reviewing you're remarks. I was stuck on ManualResetEvent
due to former design idea. I actually 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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我会在这里走不同的路线...
线程安全,无锁。或者,如果您担心环绕 Int32:
I would go a different route here...
Thread safe, no locks. Or if you are worried about wrapping around Int32:
如今,我只对一个简单的 System.Object 对象进行 lock() ,我创建该对象只是为了锁定。
我绝对不会对诸如事件之类的东西使用 lock() ,不是因为它不起作用,而是因为我认为在它本身的对象上使用 lock() 可能会相当混乱本身 (尽管完全独立)与内核锁定类型操作相关。
我不清楚你实际上在这里做什么,但它看起来很像一个名为互斥体可能会做得更好的事情。
Nowadays, I only ever lock() on a simple System.Object object which I've created just for locking with.
I definitely wouldn't lock() on something like an Event, not because it wouldn't work, but because I think it's potentially rather confusing to be using lock() on an object which it is itself (though completely separately) associated with kernel locking type operations.
I'm not clear what you're actually doing here, but it looks rather like something which a named Mutex might do better.
我认为最好在对象上使用 lock() 。
另外,您可以通过使用“双重检查锁定”来防止过多的线程锁定,
例如
注意... - 关于双重检查锁定有一些有趣的评论 - .NET 中的双重检查锁定 - 我仍在阅读此内容!
另请注意...从您发布的代码片段中尚不清楚,但如果您希望实现全局单例,则解决方案 4 位于 http://www.yoda.arachsys.com/csharp/singleton.html 是一个很好的起点
I think it's better to use lock() for this on an object.
Also, you can prevent excess thread locking by using a "double-checked locking"
e.g.
Note... - there's some interesting comments on double-checked locking - Double-checked locking in .NET - I'm still reading up on this!
Another note... its not clear from the code snippet you posted, but if you are looking to implement a global singleton then solution 4 on http://www.yoda.arachsys.com/csharp/singleton.html is a good place to start
您唯一需要确保的是,需要同步的代码的所有实例都可以访问您锁定的同一对象。除此之外,没有问题。
The only thing you need to make sure is that the same object you lock on is accessible to all instances of the code that needs synchronizing. Other than that, no problem.