使用AddHandler时是否需要EnterWriteLock?

时间:2009-07-25 20:33:07

标签: .net vb.net multithreading

使用ReadWriteLockSlim进行多线程支持时,使用AddHandler时是否需要EnterWriteLock?

以下两个例子可以帮助说明我的观点:

AddHandler ClassInstance.Event, New EventHandler(AddressOf Me.Method)  

- 或 -

Me.ReaderWriterLockSlimInstance.EnterWriteLock()
AddHandler ClassInstance.Event, New EventHandler(AddressOf Me.Method)  
Me.ReaderWriterLockSlimInstance.ExitWriteLock()

1 个答案:

答案 0 :(得分:2)

这可能取决于事件;例如,如果您通过“类似字段的事件”使用C#编写的dll消耗事件,即

public event EventHandler SomeEvent; // synchronized

(是的,我知道你问过VB;我在下面解释一下......)

然后这是(根据C#语言规范)自动同步,因此没有多线程问题(这里代理是不可变的有帮助)。但是,即使在同一个库中,非类似场的事件也可能同步 - 即

private EventHandler myField;
public event EventHandler SomeEvent { // not synchronized
    add { myField += value; }
    remove { myField -= value; }
}

我知道你问过VB ......但你问的是VB是 comsumer 。我的观点是,它取决于发布者

因此,如果你无法控制发布者,那么手动同步声音可以建议如果你认为这种情况存在线程风险(在大多数情况下,不需要同步;但是如果你知道这是一个螺纹区域,那么同步是明智的。)

另请注意,提升事件时的常见模式是拍摄快照:

protected virtual void OnSomeEvent() {
    EventHandler handler = SomeEvent; // assume the "field-like" version
    if(handler!=null) handler(this, EventArgs.Empty);
}

我的观点在这里是理论上订阅者即使在他们认为已经取消订阅之后也可以接收这样的事件,所以如果您可能想要的极端情况可以手动处理,也许通过在某处保留标志(或只是异常处理)。


根据要求,VB中的最后一个代码片段(通过反射器)进行比较:

Protected Overridable Sub OnSomeEvent()
    Dim handler As EventHandler = Me.SomeEvent
    If (Not handler Is Nothing) Then
        handler.Invoke(Me, EventArgs.Empty)
    End If
End Sub