【问题标题】:Event Handler Stops Working After Dispose处理后事件处理程序停止工作
【发布时间】:2014-01-23 18:19:21
【问题描述】:

以下三个 ImageButton 被添加到页面代码隐藏中的面板 (pBreakfast):

ImageButton ibSR = new ImageButton();
ibSR.ID = "ibStickyRoll";
ibSR.ImageUrl = "/images/Breakfast.gif";
ibSR.Click += new ImageClickEventHandler(ImageButton_Click);
pBreakfast.Controls.Add(ibSR);

ImageButton ibD = new ImageButton();
ibD.ID = "ibDoughnut";
ibD.ImageUrl = "/images/Breakfast.gif";
ibD.Click += new ImageClickEventHandler(ImageButton_Click);
pBreakfast.Controls.Add(ibD);
ibD.Dispose();

using(ImageButton ibC = new ImageButton()){
   ibC.ID = "ibCrepe";
   ibC.ImageUrl = "/images/Breakfast.gif";
   ibC.Click += new ImageClickEventHandler(ImageButton_Click);
   pBreakfast.Controls.Add(ibC);
}

我希望这三个都可以工作,或者处置的 ImageButtons 会产生错误或根本不出现。但是发生的事情是所有三个都出现并且不会导致任何错误,但是事件处理程序永远不会为已释放的 ImageButton 触发。

为什么处置只导致事件处理程序连接消失?

我正在将 TableRow 和 TableCell 动态添加到同一页面上的表格中,并将 ImageButtons 放置在每一行的一个单元格中。我正在使用 TableRow 和 TableCell 的“使用”,没有任何问题。处理外部(TableRow 和 TableCell)对象似乎没有问题;只要我不处理动态 ImageButtons,事件处理程序就会在点击时触发 OK。

在这种情况下,永远不要处理 ImageButtons 可以吗?我已将 StackOverflow 的建议牢记在心,并尝试在我所有的一次性对象上使用 using() —— 所以这真的让我很烦恼。

谢谢!

【问题讨论】:

    标签: c# asp.net code-behind dispose


    【解决方案1】:

    只有在一切都完成后才处置一个对象。在对象被释放后尝试对其进行任何操作将导致未定义的行为。将其视为释放内存。

    幸运的是,当您关闭窗体时,Windows 窗体会为您处理这些对象。您需要在代码中处理它们的唯一情况是从表单中删除对象。

    看看 .Designer.cs 文件,你会看到表单的 Dispose() 方法:

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    

    components.Dispose() 将递归清理表单上的所有组件,包括面板中的组件。

    【讨论】:

    • 感谢您的回复,白鲸。不过,我不禁认为还有更多。即使在 pBreakfast 中有对它的引用, dispose() 是否会立即发生?我认为 pBreakfast.controls 中的新 ImageButton 现在属于 pBreakfast 并且在清理 pBreakfast 之前不会发生处置。这让我很困惑。如果我不应该在 .Add() 之后处理 ImageButton,为什么它是一次性的?另外,这个解决方案没有designer.cs(至少我找不到),我在服务器上使用按需编译。 :^)
    • 处置不会立即发生。只有当某些东西显式调用 Dispose() 时才会发生。当您说 pBreakfast.controls 中的新 ImageButton 现在属于 pBreakfast 并且在清理 pBreakfast 之前不会发生处置时,您是正确的。这正是你想要的。在 ImageButton 上调用 Dispose() 之后,ImageButton 就没用了。死的。卡普特。你不想创建一个 ImageButton,把它交给 pBreakfast,然后销毁它! ImageButton 是一次性的,因此可以在表单完全消失后对其进行清理。
    • 另外,我是个傻瓜,错过了这是 ASP.NET 而不是 WinForms。对于那个很抱歉。但它仍然存在:不要在其他人使用该对象时丢弃它。
    • 为了结束这一点,您是否会说动态添加表格行的正确方法是不显式处理 TableRow、它的 TableCells 或 TableCells 的任何内容(例如 ImageButtons)无论页面是否可以对某些对象进行显式处理?或者,如果页面在处理到位的情况下工作,请将它们留在里面?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 2022-06-18
    • 1970-01-01
    • 2014-05-06
    • 2018-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多