Silverlight:Memory Leak处理
Silverlight开发中可能会遇到各种内存泄露的情形,由于CLR本身给我们提供了垃圾回收功能,所以在一般的情况下,我们也可能不是太重视内存是否得到有效的释放,
本文试图还原自己遇到一个场景,给各位做Silverlight的朋友们一个参考.
那么我处理的情形是在Silverlight自带的导航框架中遇到的,我将ViewModel绑定到对应的View中,唯一的区别是我的Viewmodel中包含了一个DispatcherTimer.
看我的Viewmodel的代码:
public class AboutViewModel : ViewModelBase,IDisposable
{
public static Lazy<DispatcherTimer> _dispatcher;
private string _currentDateTime;
public AboutViewModel()
{
_dispatcher = new Lazy<DispatcherTimer>();
_dispatcher.Value.Interval = TimeSpan.FromSeconds(1);
_dispatcher.Value.Tick += _dispatcher_Tick;
_dispatcher.Value.Start();
}
public string CurrentDateTime
{
get { return _currentDateTime; }
set { _currentDateTime = value;
Notify(()=>CurrentDateTime);
}
}
void _dispatcher_Tick(object sender, EventArgs e)
{
_dispatcher.Value.Tick -= _dispatcher_Tick;
CurrentDateTime = DateTime.Now.ToLongTimeString();
_dispatcher.Value.Tick += _dispatcher_Tick;
}
public void Dispose()
{
_dispatcher.Value.Stop();
_dispatcher = null;
}
<TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}"
Text="{Binding CurrentDateTime,Mode=TwoWay}"/>
这个典型的MVVM模式的应用,不过问题也随之出现了:
当你切换到home页面时,理论上about页面已经被销毁,但是如果你此时在AboutViewModel中的_dispatcher_Tick处断点时,你会发现它仍然在执行Tick事件.你尝试在Dispose方法断点时,你会发现
切换页面时,也确实没有调用到这个方法.
需要强调的一点是,上面这个例子并不是因为由于MVVM模式才导致内存泄露,而是事件强引用本身没有得到释放.
那么我最终处理的方式是Page的Unload事件中调用Dispose方法.
public About()
{
InitializeComponent();
DataContext = new AboutViewModel();
this.Unloaded += new RoutedEventHandler(About_Unloaded);
}
void About_Unloaded(object sender, RoutedEventArgs e)
{
(DataContext as AboutViewModel).Dispose();
}
关于Silverlight内存泄露的文章,网上也说了很多了,本例子希望给遇到的朋友一个简单的处理方式,如果对上面的例子有更好的方式,希望能提出来分享.
代码下载:内存泄露示例