我正在使用UWP(通用Windows 10应用程序)社区工具包中的一个名为WeakEventListener
的源代码(源代码可用here)来订阅事件,同时允许侦听器由垃圾收集器完成,因为这在我的项目过去一直是内存泄漏的来源。绝对关键的一点是分配给OnEventAction和OnDetachAction的委托不得包含闭包(即对监听器的强引用,或this
)。但是看起来我总是在关闭,即使我不在委托中使用this
(通常是lambda表达式)。下面是一个示例lambda表达式(在TransitMap类的构造函数中,它有一个名为AddIns_CollectionChanged的私有方法):
addInsListener.OnEventAction = (map, obj, e) => map.AddIns_CollectionChanged(obj, e);
但是当我在WeakEventListener类中强制执行没有闭包的委托时:
private Action<TInstance, TSource, TEventArgs> _OnEventAction;
/// <summary>
/// Gets or sets the method to call when the event fires.
/// </summary>
public Action<TInstance, TSource, TEventArgs> OnEventAction
{
get { return _OnEventAction; }
set
{
if (value?.Target != null)
throw new Exception("Any delegate passed to a WeakEventListener must be static, otherwise a memory leak exists.");
_OnEventAction = value;
}
}
问题是委托总是有一个非空的Target,即使它本身没有引用this
!有谁知道为什么会这样?
更新:以下是我班上的一些相关代码,这是证明问题的最低要求。
public sealed class TransitMap : UserControl
{
private ObservableCollection<TransitMapAddInBase> AddIns = new ObservableCollection<TransitMapAddInBase>();
public TransitMap()
{
WeakEventListener<TransitMap, object, NotifyCollectionChangedEventArgs> addInsListener = new WeakEventListener<TransitMap, object, NotifyCollectionChangedEventArgs>(this);
//Problem line. Lambda expression holds up a strong reference to 'this' (in its Target) despite using a parameter for the listener instead of this.
addInsListener.OnEventAction = (map, obj, e) => map.AddIns_CollectionChanged(obj, e);
AddIns.CollectionChanged += addInsListener.OnEvent;
}
private void AddIns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
//Do something...
}
}