最近,我试图理解事件的类似字段的实现。 MSIL代码不够清晰,因此我使用sharplab.io来查看没有语法糖的c#代码,并收到以下消息:
private Action m_Someevent;
public event Action Someevent
{
[CompilerGenerated]
add
{
Action action = this.m_Someevent;
Action action2;
do
{
action2 = action;
Action value2 = (Action)Delegate.Combine(action2, value);
action = Interlocked.CompareExchange(ref this.m_Someevent, value2, action2);
}
while ((object)action != action2);
}
[CompilerGenerated]
remove
{
Action action = this.m_Someevent;
Action action2;
do
{
action2 = action;
Action value2 = (Action)Delegate.Remove(action2, value);
action = Interlocked.CompareExchange(ref this.m_Someevent, value2, action2);
}
while ((object)action != action2);
}
}
do while
循环的作用是什么?我已经调试了许多订阅情况,并且始终只循环一次。我有一个想法,它用于invocattionlist
上的迭代,但这是错误的。
答案 0 :(得分:2)
即使在多线程情况下,事件添加和删除也被设计为原子的。您应该能够从两个线程订阅给定事件,并确保两个都被添加。
这是通过读取基础字段的值,将委托与要添加的委托相结合,尝试将其分配回该字段并仅在分配给您的字段中的值是在添加您的值之前,最初存在的值。实际上,它在检查早期代码行中的工作时会检查基础字段是否更改。如果有,它将再次尝试,直到在获取和设置字段之间没有发生任何其他事情为止。