调用EventHandler

我有以下EventHandler:

private EventHandler _myEventHandler; public event EventHandler MyEvent { add { _myEventHandler += value; } remove { _myEventHandler -= value; } } 

有人可以解释以下片段之间的区别吗?
Snippet EventHandler(A):

 //Snippet A: if (_myEventHandler != null) { _myEventHandler(new MyEventArgs()); } 

Snippet BeginInvoke(B):

 //Snippet B: if (_myEventHandler != null) { _myEventHandler.BeginInvoke(new MyEventArgs(), ar => { var del = (EventHandler)ar.AsyncState; del.EndInvoke(ar); }, _myEventHandler); } 

为了澄清:调用EventHandler“就像它”和使用BeginInvoke什么区别?

BeginInvoke方法是异步的,这意味着它是在不同的线程上引发的。 如果人们不期望它,这可能是危险的,并且事件非常罕见 – 但它可能很有用。

另外,请注意, 严格来说,您应该对事件处理程序值进行快照 – 如果(通过Begin* )您正在处理线程,则尤其如此。

 var tmp = _myEventHandler; if(tmp != null) { tmp(sender, args); } 

另外 – 请注意,您的事件订阅本身不是线程安全的; 再次,这只在你处理multithreading时很重要,但内置的类字段事件线程安全的:

 public event EventHandler MyEvent; // <===== done; nothing more 

这里避免的问题是:

  • 使用快照,我们避免了最后一个订阅者在null-check和invoke之间取消订阅的风险(这确实意味着他们可能得到他们没想到的事件,但这意味着我们不会杀死提升线程)
  • 通过类似字段的事件更改,我们可以避免在两个线程同时执行此操作时丢失订阅/取消订阅的风险

BeginInvoke()调用immediatelly将控制返回给调用线程,并在与ThreadPool的单独线程中运行委托,因此这将是某种异步执行。