【问题标题】:implementing Dispose and Finalize for Windows phone silverlight Pages为 Windows phone silverlight Pages 实现 Dispose 和 Finalize
【发布时间】:2015-02-26 21:17:17
【问题描述】:

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

尝试

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

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

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

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

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

调查

我已阅读以下解决此问题的内容: StackOverFlow: 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 的页面实现 dispose 和 finalize 方法?

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

非常感谢 Windows 手机的示例。


使用 Dispose 进行初始尝试

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

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()

我见过不同的实现,要么在 dispose 函数中使用this = null,要么使用base.Dispose()。我认为后者只能在类为IDisposable 的情况下使用?这是要走的路吗?如果是这样,我该怎么做?

使用 Microsoft Profiler

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

【问题讨论】:

  • 看在上帝的份上:除非有令人信服的理由,否则请不要在生产代码中使用 GC.Collect
  • 对于内存问题,使用内存分析器并找出您认为不应该存在的对象存在的原因。
  • @SriramSakthivel 我知道在 c# 中这不是首选的解决方案,这应该自动完成。但由于我遇到问题,我尝试了解决方案。请解释什么是内存分析器,并请我参考。我只使用实时更新的内存,以便我可以实时测试应用程序并查看内存使用情况
  • Refer this 获取分析帮助。 Visual Studio 自带分析器,做一些研究。很难解决记忆问题。你真的需要使用分析器。
  • @JTIM 你必须记住,如果有一些根对象保持对你的对象的强引用,使用Dispose 或编写终结器对你没有帮助。要走的路不是实施任何这些。你应该做的是下载一个内存分析器start here 并尝试找到让你的对象保持活力的根。

标签: c# mvvm memory-leaks windows-phone dispose


【解决方案1】:

实际上没有必要在用户离开页面时进行处理,重新创建对象的性能
影响超过在应用程序处于活动状态时在内存中拥有页面的内存负载.
您应该在从内存中删除对象与再次重新创建同一组对象之间做出决定。
话虽如此,您应该小心导航模型。 如果您在每次用户导航到页面时都创建对象,但在用户导航离开时并未实际处理,则可能会出现内存问题。
为此,我建议您充分理解应用程序中的PageBaseNavigationHelperNavigationService 类。 您提到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;
         }
        }
}

【讨论】:

  • 感谢您的回复。第一页只是一个带有一些动画的登录页面。因此,导航离开后应删除所有图形和页面。我很抱歉没有说清楚。对于dispose,很多元素里面并没有dispose函数。因此,我的问题也是如何在下面的类中创建处置,以便将它们完全删除。正如您所说, null 是不够的,因此我对在这种情况下该怎么做很感兴趣。感谢您的深入回答。
  • 如果类没有 Dispose ,只需设置对 null 的引用,确保您没有在内存中保存任何可能阻止对象被 GC 的引用。在您的情况下,您可以检查您不再需要的页面是否没有在代码中的任何地方引用,例如导航堆栈。
  • 好的,谢谢您提供的信息,由于某种原因,当我将其设置为 null 时,内存增加了?我已经尝试过代码并且我不应该有任何参考,当我离开时,因为我在进入新页面时删除了 backstack,这是因为我希望应用程序不依赖 backkey,因为这不会继续能得到的。但是由于某种原因,尽管我已将元素设置为null,但在我导航离开后很久,该页面仍保留在内存中。令人沮丧。我将尝试更深入地了解分析。
  • 我会奖励你 100 分,这样他们就不会浪费了,但这不是答案。这解决了这个问题,不幸的是我:/
【解决方案2】:

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

Remove Pages windows phone

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

【讨论】:

    猜你喜欢
    • 2011-05-25
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 2011-03-31
    • 2014-11-21
    • 1970-01-01
    相关资源
    最近更新 更多