【发布时间】:2016-11-06 15:49:10
【问题描述】:
我正在尝试使用事件聚合器,并将操作存储在包装类中,在其中我将实际操作方法存储为Delegate,而操作方法所在的类为WeakReference。
当我想调用事件处理程序时,我首先检查 WeakReference.IsAlive 是否为真。如果是,则调用它,否则我将其从集合中删除,因为这意味着它所属的对象已被清空/垃圾收集。
但是,当我创建一个匿名操作并将其添加到我的事件聚合器时,它始终处于活动状态,即使我将父类设为空(并强制运行垃圾收集器)。
如何让 IsAlive 将匿名方法设置为 FALSE?
void AddHandler<TEvent>(Action<TEvent> callback) {
InternalHandler handler = new InternalHandler(callback);
// Store the handler somewhere to use the callback later, if it still alive
}
class InternalHandler {
WeakReference _reference;
Delegate _method;
public InternalHandler(Delegate handler) {
_reference = new WeakReference(handler.Target);
Type messageType = handler.Method.GetParameters()[0].ParameterType;
Type delegateType = typeof(Action<,>).MakeGenericType(handler.Target.GetType(), messageType);
_method = Delegate.CreateDelegate(delegateType, handler.Method);
}
bool IsAlive => _reference != null && _reference.IsAlive;
bool Invoke(object data) {
if (!IsAlive) return false;
if (_reference.Target != null) _method.DynamicInvoke(_reference.Target, data);
return true;
}
}
在测试应用中
TempObject t = new TempObject();
// Some time later
t = null;
GC.Collect();
class TempObject {
public TempObject() {
myHandler.AddHandler<SomeObject>(o => {
// Some code with a breakpoint
});
}
}
在调用GC.Collect()并发出一个新事件后,t中的匿名方法中的断点仍然被调用!
如何为匿名方法获取正确的WeakReference?
【问题讨论】:
标签: c# delegates garbage-collection action weak-references