【发布时间】: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