调用事件处理程序

2024-04-12

我有以下事件处理程序:

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(使用前将#替换为@)

调用事件处理程序 的相关文章

随机推荐