查询一名代表两次,每次一个事件一名、两次、事件、代表

2023-09-04 22:59:48 作者:享受人世的糜烂。

我最近问了一个问题,会发生什么,如果我想查询一个处理两次。让我告诉你code:

I was recently asked a question what will happen if I would query one handler twice. Let me just show you code:

 public delegate void OpenEventHandler(object sender, EventArgs e);

 public class MyWindow
 {
     public event OpenEventHandler Open;

     public void OpenWindow()
     {
         if (Open != null)
         {
             Open(this, new EventArgs());
         }
     }
 }

 public class TwoDelegates
 {
     public static void HandleOpen(Object sender, EventArgs e)
     {
         Console.WriteLine("Birds fly");
         (sender as MyWindow).Open -= HandleOpen;
     }

     public static void Run()
     {
         var window = new MyWindow();
         window.Open += HandleOpen;
         window.Open += HandleOpen;

         window.OpenWindow();
         Console.ReadKey();
     }
 }

我不知道为什么字符串仍然打印两次。在它开始调用列表包括两个项目具有相同的委托引用,但第一次运行后,它被清理,仍然出现塞康invocaiton。

I wonder why string is still printed twice. On the beginning of it Invocation list consist of two items with same delegate reference, but after a first run it is cleaned up, still the secon invocaiton appears.

UPDATE1:

似乎连简单的 = - 只删除一个条目:

Seems that even simple -= removes only one entry:

 var window = new MyWindow();

 window.Open += HandleOpen;
 window.Open += HandleOpen;

 Console.WriteLine(window.getHandlers().Count());
 window.Open -= HandleOpen;
 Console.WriteLine(window.getHandlers().Count());

尽管调试模式在VS2010,当你通过的window.open 内部属性显示为空的调用列表0计数。看来,它的一些魔术VS中显示调试信息。

Though debug mode in VS2010, while you look through window.Open internal properties shows empty invocation list with 0 count. Seems that it's some magic in debug info displayed in VS.

推荐答案

要展开什么Servy说,这里就是你的code稍微修改后的版本,有一些调试助手澄清这是怎么回事。在HandleOpen功能,我们检查事件处理程序之前,并从事件中除去HandleOpen后。总结是:有HandleOpen的两个副本在你的组播,没有理由为一个单一开路= HandleOpen以消除他们两个。

To expand on what Servy said, here's a slightly modified version of your code, with some debugging helpers to clarify what's going on. In the HandleOpen function, we examine the event handlers before and after removing HandleOpen from the event. The summary is: There's two copies of HandleOpen in your multicast, there's no reason for a single Open-=HandleOpen to remove both of them.

public class MyWindow
{
    public event OpenEventHandler Open;

    public void OpenWindow()
    {
        if (Open != null)
        {
            Open(this, new EventArgs());
        }
    }

    public Delegate[] getHandlers()
    {
        return Open.GetInvocationList();
    }
}

public class TwoDelegates
{
    public static void HandleOpen(Object sender, EventArgs e)
    {
        Console.WriteLine("Birds fly");
        var thisWin = sender as MyWindow;
        var before = thisWin.getHandlers();

        (sender as MyWindow).Open -= HandleOpen;
        var after = thisWin.getHandlers();

    }

    public static void Run()
    {
        var window = new MyWindow();
        window.Open += HandleOpen;
        window.Open += HandleOpen;

        window.OpenWindow();
        Console.ReadKey();
    }
}
 
精彩推荐