我有以下事件处理程序:
private EventHandler<MyEventArgs> _myEventHandler;
public event EventHandler<MyEventArgs> MyEvent
{
add { _myEventHandler += value; }
remove { _myEventHandler -= value; }
}
有人可以解释以下片段之间的区别吗?
事件处理程序片段 (A):
//Snippet A:
if (_myEventHandler != null)
{
_myEventHandler(new MyEventArgs());
}
BeginInvoke 片段 (B):
//Snippet B:
if (_myEventHandler != null)
{
_myEventHandler.BeginInvoke(new MyEventArgs(), ar =>
{
var del = (EventHandler<MyEventArgs>)ar.AsyncState;
del.EndInvoke(ar);
}, _myEventHandler);
}
为了澄清:“按原样”调用 EventHandler 和使用BeginInvoke
?
The BeginInvoke
方法是异步的,这意味着它是在不同的线程上引发的。如果人们没有预料到,这可能会很危险,而且对于事件来说非常罕见 - 但它可能很有用。
另外,请注意严格来讲你应该快照事件处理程序值 - 这是尤其true 如果(通过Begin*
)你正在处理线程。
var tmp = _myEventHandler;
if(tmp != null) {
tmp(sender, args);
}
另请注意您的活动订阅itself不是线程安全的;再说一次,这仅在您处理多线程时才重要,但是内置的类似字段的事件is线程安全:
public event EventHandler<MyEventArgs> MyEvent; // <===== done; nothing more
这里避免的问题是:
- 通过快照,我们避免了最后一个订阅者在空检查和调用之间取消订阅的风险(这确实意味着他们可能会收到他们没有预料到的事件,但这意味着我们不会杀死引发线程)
- 通过类似字段的事件更改,我们可以避免两个线程同时执行此操作时丢失订阅/取消订阅的风险
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)