多次附加事件处理程序

24

我刚开始接触C#。我只是想知道多次附加事件处理程序是否会导致意外结果?

实际上,在我的应用程序中,我正在将事件处理程序附加到一个事件中,例如

cr.ListControlPart.Grid.CurrentCellActivated += new EventHandler(Grid_CurrentCellActivated); 

这行代码在代码中被多次调用。

3个回答

39

自己试试:

static class Program
{
    static event EventHandler MyEvent;

    static void Main()
    {
        // registering event
        MyEvent += Program_MyEvent;
        MyEvent += Program_MyEvent;
        MyEvent += Program_MyEvent;
        MyEvent += Program_MyEvent;
        MyEvent += Program_MyEvent;

        // invoke event
        MyEvent(null, EventArgs.Empty);
        Console.ReadKey();
    }

    static void Program_MyEvent(object sender, EventArgs e)
    {
        Console.WriteLine("MyEvent fired");
    }
}

输出:

MyEvent fired
MyEvent fired
MyEvent fired
MyEvent fired
MyEvent fired

15
它会多次调用此事件。 - Evorlor

24

在添加之前取消订阅即可预防此问题。

Object.Event -= EventHandler(method);
Object.Event += EventHandler(method);

如果可能的话,通过始终在一个地方订阅事件(比如构造函数)来防止它发生。


9
如果我们在事件处理程序尚未订阅时尝试取消订阅,会发生什么? - BhushanK
3
@Bhushan 是的,即使在不使用时取消订阅事件也是最佳实践。垃圾回收不会立即回收此内容。 - Rajesh Subramanian
8
这种方法可行,第一次订阅时不会出现任何异常。(即“-=”会被静默忽略)。 - Dave Walker
2
只要您保留对原始函数的句柄,就没问题。但是对于使用lambda或new关键字声明的匿名方法,这种方法效果不佳 ;) - theMayer

15

如果您不断添加事件处理程序,则每次附加处理程序时都会引发该事件。 这意味着:

  • 如果您只需要引发一次,则分配一个处理程序。
  • 如果您附加了相同的处理程序4次,则它将被调用4次。

查看您的代码,与其多次钩入CurrentCellActivated事件,更有意义的是订阅一次通用的CellActivated事件。


1
这意味着如果事件处理程序被附加了10次,那么每当事件被触发时,处理程序将被调用10次? - BhushanK
@Jamse 实际上我在玩下拉网格的网格单元格,但没有像 "CellActivated" 这样的事件。 - BhushanK
1
“每个实例”是不明确的。如果您使用相同的处理程序实例订阅12次,则在事件触发时它将被调用12次。 - Bill Tarbell
@BillTarbell 恩,回想起来措辞不当,随意编辑吧 :) - James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接