【问题标题】:How to unhook eventhandlers in C#如何在 C# 中取消挂钩事件处理程序
【发布时间】:2010-11-05 13:54:40
【问题描述】:

我正在开发一个具有多种形式的 C# 应用程序。
当我打开其中一个表单时,我会添加一个这样的事件侦听器:SomeClass.MotionCompleted += new EventHandler(HandlerMethod);。 MotionCompleted 事件是一个静态事件

我注意到,在关闭此表单后,当事件发生时仍会调用 HandlerMethod,这会导致异常,因为它会尝试更新表单上不再存在的内容。

即使表单不再存在,事件监听器如何存在并响应事件?一旦 form.Close() 或 this.Close() 被调用,不应该自动解除事件监听器的钩子以便它们不再被调用吗?

【问题讨论】:

    标签: c# winforms event-handling formclosing


    【解决方案1】:

    这就是静态事件的弊端! :) 你有一个managed leak 那里。

    覆盖表单的 OnClosing 并取消注册您的处理程序:

    protected override void OnClosing(CancelEventArgs e) {
        SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
    }
    

    【讨论】:

    • 我想这就是答案,我只是希望有一种方法可以自动完成!
    • 您应该阅读 .net 垃圾收集器。因为该事件是静态的,所以它是一个“根”对象,其中包含一个处理程序,其中包含对您的表单的引用。由于该引用,即使您认为它不存在,您的表单仍然有效。
    • OnFormClosing 在技术上不正确,它可能会被取消。使用 OnFormClosed。从设计器文件中剪切和粘贴 Dispose() 方法更加正确。这是自动的。
    • @hans +1,然而,OnClosing 为用户留下了一些潜在的未来乐趣,从而更好地了解 .net 包装的 winform 的工作原理。
    【解决方案2】:
    Someclass.MotionCompleted -= new EventHandler(HandlerMethod);
    

    这篇文章展示了很多关于 C# 事件的提示:http://www.yoda.arachsys.com/csharp/events.html

    【讨论】:

      【解决方案3】:

      要添加到所有重复的答案,您也可以这样解开:

      SomeClass.MotionCompleted -= HandlerMethod;
      

      无论您使用-= HandlerMethod 还是-= new EventHandler(HandlerMethod),输出的汇编代码都是相同的。

      【讨论】:

        【解决方案4】:
        SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
        

        只需将“+”改为“-”

        【讨论】:

          【解决方案5】:

          您可以使用此代码示例:

          SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
          

          但是,您必须小心将您的事件与包含HandlerMethod 的对象实例与注册它的对象解除挂钩。

          【讨论】:

            【解决方案6】:

            您需要像这样手动取消挂钩事件: SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);

            【讨论】:

              【解决方案7】:

              不完全是。垃圾收集器不会收集表单,因为事件处理程序仍然存在。静态事件处理程序不会自行解开。您可以在 onClosing 方法中取消挂钩任何分配的事件,例如:

              SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
              

              之后一切都应该正常了。

              【讨论】:

                【解决方案8】:

                事件是强引用:除非您明确取消对它们的引用,否则它们不能被垃圾回收。

                这就是为什么我建议你编写一个 subscribe 和一个 unsubscibe 方法来完成它们的工作并集中这个钩子(如果你不释放它们会导致内存泄漏)

                private void subscribeAll()
                {
                  SomeClass.MotionCompleted += new EventHandler(HandlerMethod);
                  // other subscription
                }
                
                private void unSubscribeAll()
                {
                  SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
                  // other subscription
                }
                

                【讨论】:

                  【解决方案9】:

                  你必须手动解开:

                  SomeClass.MotionCompleted -= HandlerMethod;
                  

                  【讨论】:

                    猜你喜欢
                    • 2021-12-01
                    • 2016-02-03
                    • 1970-01-01
                    • 2021-01-12
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多