首页 > 解决方案 > 作为事件处理程序的匿名方法

问题描述

编辑:这个问题不是关于如何取消订阅事件,因为如果我愿意,我知道该怎么做。问题是在我的特定场景中是否与垃圾收集存在冲突。

在我不久前编写的一些代码中,我通过匿名方法注册了一个事件( CheckExecution,拥有者,见下面的代码)。isoDataTemp但是现在我想到给一个事件分配一个匿名方法是非常邪恶的,因为没有办法从事件中注销该方法,对吧?我曾经遇到过一个无法被垃圾收集的对象的问题,因为一个事件仍然指向它。

所以我想知道我是否可以在这里遇到麻烦。我的自发反应是“不,因为匿名方法属于 MainForm,它的生命周期比它的isoDataTemp成员长”。但我不确定。闭包呢?匿名方法是否完全属于 MainForm。我很困惑...

public partial class MainForm : Form
{
    // ...

    void BackgroundWorkerISOAnalysisDoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        int prog = 0;

        isoDataTemp.CheckExecution += () => 
        {
            prog += 12;
            if (prog > 100) prog = 100;
            worker.ReportProgress(prog);
            return !worker.CancellationPending;
        };

        isoDataTemp.Analyze();

        if (worker.CancellationPending) e.Cancel = true;
    }
}

标签: c#.neteventsanonymous-methods

解决方案


要取消注册您拥有的事件的所有事件处理程序,只需使用以下代码:

isoDataTemp.CheckExecution = null;

请注意,这适用于匿名和非匿名事件处理程序。

从您的示例中,您可以将此代码添加到 OnFormClosing 事件中,以确保正确且完全删除分配给您的 isoDataTemp 对象的事件。

请注意,如果 isoDataTemp 对象是表单对象的子对象,那么当您的 Form 对象被销毁时,它将被删除,并将与被销毁的 Form 对象实例一起进行垃圾收集,如预期的那样。


推荐阅读