为 Windows phone silverlight 页面实施 Dispose 和 Finalize

implementing Dispose and Finalize for Windows phone silverlight Pages

我有一个包含图形、弹出窗口和动画的大型解决方案。我发现我在页面导航期间有大量内存泄漏。

尝试

因此我尝试了第一个解决方案:

protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        if (App.RootFrame.CanGoBack)
            App.RootFrame.RemoveBackEntry();
        GC.Collect();
        base.OnNavigatedTo(e);
    }

这来自 MSDN 和 Whosebug 上的多个来源,应该删除为页面存储的内存。事实并非如此,我不确定代码的 MVVM 结构是否以某种方式保存了信息。然后,当事件被触发时,我尝试实现解构函数并将值强制为空:

~SecondScreen()
    {
        In_Game_Crest = null;
        currentViewModel = null;
    }

这是我为所有页面、弹出窗口和用户控件所做的。然后我再次使用调试检查代码,并且没有页面解构器被触发。这导致我尝试使用 IDisposable 并摆弄 MVVMLight 提供的 viewmodelLocator,但没有成功。

调查

我已阅读以下解决问题的内容: Whosebug: Finalizer and Dispose

Finalize/Dispose pattern in C#

MSDN: Implementing a Dispose Method

MSDN: Implementing Finalize and Dispose to Clean Up Unmanaged Resources

问题

但它让我困惑多于对我的帮助。我应该如何为我的 windows phone?

实现页面的处理和完成方法

由于我使用的是 MVVM 结构,这些方法应该在 ViewModel 中还是在给定页面后面或两者中实现?

windows phone 的示例将不胜感激。


初次尝试 Dispose

我已经阅读了更多有关该主题的内容,发现可能不应该写 finalize?但我仍然不确定。但是基于这个和上面的第一个 MSDN link,我尝试了以下方法:

private bool disposed = false;

    public void Dispose()
    {
        Dispose(true);
        // Take yourself off the Finalization queue 
        // to prevent finalization code for this object
        // from executing a second time.
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
  // Check to see if Dispose has already been called.
  if(!this.disposed)
  {
     // If disposing equals true, dispose all managed 
     // and unmanaged resources.
     if(disposing)
     {
        // Dispose managed resources.
         currentView = null;
         popup = null;
         Image1 = null;
         Image2 = null;
     }
          // Release unmanaged resources. If disposing is false, 
          // only the following code is executed.
          this.Content = null;
          // Note that this is not thread safe.
          // Another thread could start disposing the object
          // after the managed resources are disposed,
          // but before the disposed flag is set to true.
          // If thread safety is necessary, it must be
          // implemented by the client.

  }
  disposed = true;         
    }

    // Use C# destructor syntax for finalization code.
    // This destructor will run only if the Dispose method 
    // does not get called.
    // It gives your base class the opportunity to finalize.
    // Do not provide destructors in types derived from this class.

    ~FirstPage()
    {
        Dispose(false);

    }
    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        this.Dispose();
        base.OnNavigatedFrom(e);
    }

但是,但是,当我进入第二个屏幕时,这只是让我的内存增加了 23MB。这又让我想到了这个问题,我应该如何以及应该尝试实现什么,为什么内存会增加?

this = null, base.Dispose()

我见过不同的实现,要么在处理函数中使用 this = null,要么使用 base.Dispose()。我认为后者只能在 class 为 IDisposable 时使用?这是要走的路吗?如果可以,我该怎么做?

使用 Microsoft Profiler

所以我使用探查器来验证 FirstPage 没有被删除 从上图可以看出第一页是存在的。在评论中,我被告知要查找实例并引用元素。因此,我选择了 firstpage 的实例并得到: 这里确认 FirstPage 从未被销毁。但我被困在这里,我应该如何解释数据? 希望得到一些帮助。

当用户离开页面时,实际上没有必要处理,重新创建对象的性能
影响超过了在内存中保留页面的内存负载该应用程序还活着。
您应该在从内存中删除对象 vis.a.vis 和再次重新创建同一组对象之间做出决定。
话虽如此,您应该小心导航模型。 如果您在每次用户导航到页面时都创建对象但在用户导航离开时实际上没有释放,则可能会出现内存问题。
为此,我建议您充分理解应用程序中的 PageBaseNavigationHelperNavigationService class。 您已经提到 FirstPage 在应用程序的生命周期内不会从内存中删除,这对我来说是理想的。
将调试点放置在代码中可能会创建重对象的地方; 导航几次到不同的页面,然后返回。
检查行为,然后您可能会清楚地了解自己。
对于所有对象,请检查您是否手动调用 Dispose.
Dispose 是一个与 GarbageCollector 完全不同的概念,Dispose 只是开发人员应该遵守的契约,通过调用它来释放他们认为不再需要在内存中维护的资源,因为平台的垃圾收集发生在不确定的时间。
在您发布的示例中,我看到您将对象设置为 null 而没有实际处置。设置为 null 只是更改变量指向的内存位置。 它不会立即销毁对象。理想的配置应该如下所示。

//Call on OnClosing or OnExit or similar context
protected override void Dispose(bool isDisposing)
{

        if(isDisposing && !_isDisposed){
         if(disposeableImage != null){
           disposeableImage.Dispose();
           disposeableImage = null;
         }
        }
}

所以我为解决页面内存泄漏所做的就是使用这个问题的答案:

仍然存在一些泄漏,这有助于删除故事板和事件处理程序,以及添加和删除它们。但是一些内存仍然存在,但没有发生泄漏。