可能重复:
Do event handlers stop garbage collection from occuring?
我有一个像这样的wp7应用程序:
private void button1_Click(object sender, RoutedEventArgs e)
{
GeoCoordinateWatcher watcher = new GeoCoordinateWatcher();
watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
watcher.Start();
}
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
Debug.WriteLine(e.Position.Timestamp.ToString());
}
单击按钮两次后,控制台将输出两次Timestamp。 但观察者是一个局部变量! 它出什么问题了? 我怎么能打扰它?
答案 0 :(得分:8)
watcher
是一个局部变量,但这不一定会影响对象。您已经要求GeoCoordinateWatcher
开始 - 我希望它能够有效地保留对自身的引用,或者在适当的位置存储它。
听起来要么你应该在点击按钮后禁用按钮,或你需要将观察者保持在一个实例变量中,以便你可以处理旧的一个并创建一个新的。 (我不确定为什么那会有用。)
编辑:由于这里有两个不正确的答案,让我先澄清一下......事件发布者(在这种情况下是观察者)引用了处理程序代理。如果这些委托引用了实例方法(就像在这种情况下那样),那么就会引用包含该方法的类型的实例:
Event publisher => delegate => instance of type with handler method
这意味着只要发布者不是垃圾回收(并且事件处理程序仍然存在),就无法收集与该委托关联的实例。它不会阻止发布者自己被垃圾收集。
换句话说,如果GeoCoordinateWatcher
没有执行“特殊”操作(可能在Start
方法中),则可以进行垃圾回收。从事件处理程序到事件发布者没有隐式引用,这会阻止它以那种方式进行垃圾回收。
答案 1 :(得分:-2)
GC实际上不会收集watcher
,因为仍然会分配事件(这意味着GeoCoordinateWatcher
实例仍然被引用,因此GC不会收集它。即使局部变量超出范围,实例仍然存活。
在watcher_PositionChanged
中分离事件处理程序,事情按预期工作。如果不这样做,则每按一次按钮就会有一个GeoCoordinateWatcher
的新实例,并且当位置发生变化时,每个实例都会调用该事件。
这是在本地创建实例/分配事件时有时会出现各种奇怪问题的原因。在像您这样的情况下,有两种可能的解决方案: