调用事件处理程序

发布于 2024-11-28 19:26:23 字数 740 浏览 4 评论 0原文

我有以下事件处理程序:

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

有人可以解释以下片段之间的区别吗?
代码段 EventHandler (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 之间有什么区别?

I have the following EventHandler:

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

Could somebody explain the difference between the following snippets?
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<MyEventArgs>)ar.AsyncState;
    del.EndInvoke(ar);
  }, _myEventHandler);
}

For clarification: What's the difference between invoking an EventHandler "just as it is" and using BeginInvoke?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酷炫老祖宗 2024-12-05 19:26:23

BeginInvoke 方法是异步的,这意味着它是在不同的线程上引发的。如果人们没有预料到,这可能会很危险,而且对于事件来说非常罕见 - 但它可能很有用。

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

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

另请注意,您的事件订阅本身不是线程安全的;再次强调,这仅在您处理多线程时才重要,但是内置的类似字段的事件线程安全的:

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

这里避免的问题是:

  • 使用快照,我们避免了最后一个的风险订阅者在空检查和调用之间取消订阅(这确实意味着他们可能会收到他们没有预料到的事件,但这意味着我们不会杀死引发线程),
  • 通过类似字段的事件更改,我们避免了丢失的风险两个线程正在执行时的订阅/取消订阅这同时

The BeginInvoke approach is async, meaning that it is raised on a different thread. This can be dangerous if people don't expect it, and is pretty rare for events - but it can be useful.

Also, note that strictly speaking you should snapshot the event handler value - this is especially true if (via Begin*) you are dealing with threads.

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

Also - note that your event subscription itself is not thread-safe; again, this only matters if you are dealing with multi-threading, but the inbuilt field-like event is thread-safe:

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

The issues avoided here are:

  • with the snapshot, we avoid the risk of the last subscriber unsubscribing between the null-check and the invoke (it does mean they might get an event they didn't expect, but it means we don't kill the raising thread)
  • with the field-like event change we avoid the risk of losing subscriptions / unsubscriptions when two threads are doing this at the same time
最后的乘客 2024-12-05 19:26:23

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

BeginInvoke() call immediatelly returns control to the calling thread and run a delegate in a separate thread from the ThreadPool, so this will be some kind of asynchronous execution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文