1)我正在研究一个项目,我看到了这段代码,我不明白Monitor.Lock语句有什么意义。有人可以解释它试图做什么吗?
2)参数名称中的postscript下划线真的很烦人,有谁看过这个命名约定?
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
}
答案 0 :(得分:0)
当多个线程尝试并行执行同一块时,Monitor.Lock会锁定代码部分。它是为了确保只有1个人正在改变/执行上下文。看看MSDN。
尽管最佳做法是锁定对象始终是静态的,但在您的情况下却不是。如果您在开放类型上实例化多个对象,则可能会出现问题。
注意一件事,在泛型静态上打开T对于不同类型是不同的,即在你的情况下Open Type类中的静态成员对于T即DateTime,string等是不同的。
在csharp中,类型的私有成员通常以前缀_
命名答案 1 :(得分:0)
我读它的方式: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;
}