Dan*_*iel 29 .net c# events multithreading thread-safety
所以我已经阅读过,而不是直接调用事件
if (SomeEvent != null)
SomeEvent(this, null);
Run Code Online (Sandbox Code Playgroud)
我应该这样做
SomeEventHandler temp = SomeEvent;
if (temp != null)
temp(this, null);
Run Code Online (Sandbox Code Playgroud)
为什么会这样?第二个版本如何变得线程安全?什么是最佳做法?
Mar*_*ell 32
IMO,其他答案错过了一个关键细节 - 委托(因此事件)是不可变的.这样做的意义在于,订阅或取消订阅事件处理程序不会简单地将/追加/删除到列表中 - 而是将列表替换为新的列表,其中包含额外(或少一个)项目.
由于引用是原子的,这意味着您可以:
var handler = SomeEvent;
Run Code Online (Sandbox Code Playgroud)
你现在有一个无法改变的严格实例,即使在下一个皮秒中另一个线程取消订阅(导致实际事件字段变为null
).
所以你测试null并调用它,一切都很好.当然,需要注意的是有还是事件的混乱场景被提出的是认为它前退订皮秒的对象!
Nig*_*rne 14
事件在代表列表中真的是语法糖.当您调用该事件时,这实际上正在迭代该列表并使用您传递的参数调用每个委托.
线程的问题在于它们可能通过订阅/取消订阅来添加或删除此集合中的项目.如果他们在迭代集合时执行此操作,则会导致问题(我认为会抛出异常)
目的是在迭代之前复制列表,这样就可以防止对列表进行更改.
注意:现在,即使您取消订阅也可以调用您的侦听器,因此您应该确保在侦听器代码中处理此问题.
最佳实践是第二种形式.原因是另一个线程可能SomeEvent
在' if
'测试和调用之间为null或更改.
归档时间: |
|
查看次数: |
13091 次 |
最近记录: |