5

OnNavigatedTo我已经订阅了各种活动

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    Loaded += Screen_Loaded;
}

我没有取消订阅此活动。不需要此页面时是否会导致任何内存问题?

4

3 回答 3

2

没有。在这种情况下,您无需取消订阅以避免内存泄漏。原因是您订阅了this. 垃圾收集器必须识别这一点并释放该对象。

但是,由于其他原因,我仍然会退订。例如,拥有平衡的资源使代码更易于阅读。如果 OnNavigatedTo 被调用两次怎么办?(实际上不知道这是否会发生)然后您将有两个订阅相同的方法。有些人会争辩说,在这种情况下取​​消订阅是多余的代码并将其删除。虽然这样是正确的,但我会反对这样的论点。

你可以试试这个简短的片段来自己尝试一下。注意:永远不要使用终结器,或者GC.Collect()除非像本例中那样了解 GC。

public class Program
{
    private class Foo
    {
        public event EventHandler FooChanged;

        ~Foo()
        {
            Console.WriteLine("Foo was collected");
        }

        public void Bar()
        {
            FooChanged += UpdateUI;
        }

        private void UpdateUI(object sender, EventArgs e)
        {
        }
    }

    public static void Main(string[] args)
    {
        var foo = new Foo();
        foo.Bar();
        foo = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.WriteLine("End of program");
        Console.ReadKey();
    }
}
于 2012-12-11T08:16:14.280 回答
2

是的,您必须取消订阅某些可能在 Metro 应用程序中自动触发的事件

例如 :

事件如

Window.Current.SizeChanged += Current_SizeChanged;

void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
{
    //your code block contining various objects and logic
}

这些事件不受您控制,因为它们在后台触发。任何可能与特定页面无关的事件(假设上述事件在 OnNavigatedTo 事件中初始化)然后您必须在 OnNavigatedFrom 等事件中取消订阅

为进一步澄清初始化此事件

Window.Current.SizeChanged += Current_SizeChanged;

并且只需保留一个断点并将窗口的大小从横向更改为捕捉模式,除非您没有取消订阅该事件,否则该事件将触发。

于 2012-12-13T12:05:18.367 回答
1

请记住:

  1. 您可能会不小心多次订阅事件(使用 -= 来避免这种情况)。
  2. 如果事件处理程序是来自某个其他对象的方法,那么该对象将不会被垃圾收集,直到该方法订阅了一个事件。
于 2012-12-11T05:43:33.173 回答