实现了BeginUpdate和EndUpdate
本文关键字:EndUpdate BeginUpdate 实现 | 更新日期: 2023-09-27 18:12:15
1)我正在做一个项目,我看到了这段代码,我不明白监视器的意义是什么。锁的声明。有人能解释一下它想做什么吗?
2)参数名中的后记非常烦人,还有人见过这种命名约定吗?
public class FieldsChangeableHelper<T> : IFieldsChangeable<T>
{
object _lock;
int _lockCount;
FieldChanges<T> _changes;
public FieldsChangeableHelper()
{
_lock = new object();
_lockCount = 0;
}
public void AddChange(T field_, object oldValue_)
{
if (_changes == null)
_changes = new FieldChanges<T>(field_, oldValue_);
else
_changes.AddChange(field_, oldValue_);
if (RaiseEvent(_changes))
_changes = null;
}
#region IFieldsChangeable Members
public void BeginUpdate()
{
if (System.Threading.Interlocked.Increment(ref _lockCount) == 1)
Monitor.Enter(_lock);
}
public void EndUpdate()
{
if (System.Threading.Interlocked.Decrement(ref _lockCount) == 0)
{
FieldChanges<T> changes = _changes;
_changes = null;
Monitor.Exit(_lock);
RaiseEvent(changes);
}
}
protected bool RaiseEvent(FieldChanges<T> changes_)
{
if (_lockCount == 0 && Changed != null && changes_ != null)
{
Changed(this, changes_);
return true;
}
return false;
}
public event FieldsChanged<T> Changed;
#endregion
}
监控。当多个线程试图并行执行同一段代码时,Lock锁定该代码部分。这样做是为了确保只有一个人在修改/执行上下文。看MSDN
虽然锁定对象始终是静态的是最佳实践,但在您的情况下它不是。如果在一个开放类型上实例化多个对象,这可能会造成一些问题。注意一件事,在泛型中,打开T上的静态对于不同的类型是不同的,也就是说,在你的例子中,打开类型类中的静态成员对于T是不同的,例如DateTime, string等。
在csharp中,类型的私有成员通常以前缀_
我读它的方式:BeginUpdate()确保当前线程调用具有对实例的独占访问权,并且一旦调用EndUpdate,更改事件实际上将被批处理并引发。作者希望自己处理递归(例如在同一线程上多次调用BeginUpdate())和一种批量UpdateEvents的机制,直到锁被释放之后。因为,当您仍然对自己有锁时,在引发事件时可能会出现死锁。事件订阅者可能想要访问您的成员,因此必须锁定已经锁定的发送方实例。
整个条件锁定是不需要的(如果我的分析当然是正确的),因为基于Monitor类的锁是递归的和计数的。
锁机制还有另一个问题,那就是:当前当一个线程持有锁时。第二个线程甚至不会等待锁,而只是在没有锁的情况下继续,因为锁是有条件的!这看起来像个大虫子!
关于命名约定。我自己用它来区分私变量与参数和局部变量。这是许多c#编码约定推荐的首选项。这在以下情况下很有帮助:
void Method(int number)
{
// no need to refer to this since:
//this.number = number;
// can be replaced with
_number = number;
}