我是否需要取消订阅c#metro应用程序中的活动?

时间:2012-12-11 04:45:14

标签: c# windows-8 microsoft-metro

我订阅了OnNavigatedTo中的各种活动,如

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

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

3 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分: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;

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

答案 2 :(得分:1)

请记住:

  1. 您可能会多次意外订阅事件(使用 - =来避免这种情况)。
  2. 如果事件处理程序是来自某个其他对象的方法,那么在方法订阅事件之前,该对象不会被垃圾收集。