【发布时间】:2011-09-08 09:09:08
【问题描述】:
我有一些工厂代码:
public MyHandlingClass Create()
{
var myHandler = new MyHandlingClass();
var myNotifier = new MyNotifyingClass();
myNotifier.Notify += myHandler.HandleNotification;
return myHandler;
}
这个想法是让MyHandlingClass 对外部信号做出反应,而无需关心发送者的类型。在不同的应用程序中,包含上述方法的工厂类可以将MyNotifyingClass 替换为能够引发类似类型事件的其他东西。
在实际代码中,MyNotifyingClass 处理来自非托管 DLL 的事件:
public class MyNotifyingClass
{
private EventHandler notify;
private UnmanagedEventHandler unmanagedNotify;
public event EventHandler Notify
{
add
{
this.notify += value;
// Hold on to a strong reference to the delegate passed into the
// unmanaged DLL, to avoid garbage collection of the delegate:
this.unmanagedNotify = HandleUnmanagedNotify;
NativeMethods.SetNotifyCallback(this.unmanagedNotify);
}
remove
{
this.notify -= value;
}
}
private void HandleUnmanagedNotify(IntPtr sender, IntPtr eventArgs)
{
this.notify(this, eventArgs.Empty);
}
}
但是当我从工厂方法返回时,不再有任何对myNotifier 实例的强引用,并且它最终会被垃圾回收,从而在我的非托管DLL 尝试调用回调时导致访问冲突。
我想以某种方式强制myNotifier 实例与myHandler 实例具有相同的生命周期。但我并不特别喜欢让MyNotifierClass 保持对处理程序对象的强引用的想法。毕竟,一旦接线到位,它对实际对象就没有进一步的用途了……
我能否以某种方式在两个班级之间建立牢固的关系,但仍然让他们不知道彼此的存在?
(编辑:长话短说,这段代码 sn-p 似乎重现了我的问题:)
[TestClass]
public class MyTests
{
public class MyHandler
{
public void Handle(object sender, EventArgs e)
{ }
}
public class MyNotifier
{
public event EventHandler Notify;
}
[TestMethod]
public void TestsSomeCondition()
{
var myHandler = new MyHandler();
var myNotifier = new MyNotifier();
myNotifier.Notify += myHandler.Handle;
var weakNotifierRef = new WeakReference(myNotifier);
myNotifier = null;
GC.Collect();
Assert.IsTrue(weakNotifierRef.IsAlive);
}
}
【问题讨论】:
-
也许弱事件可能会有所帮助:stackoverflow.com/questions/1089309/weak-events-in-net.
-
注册事件已经在链接对象了。
-
@steven :这似乎是相反的问题。我的问题是侦听器不让通知程序保持活动状态......
-
@jan :我本来是这么想的——但这里似乎不是这样。在我从工厂方法返回后,通知程序引用了其他对象,但没有人引用它 - 显然使它适合 GC...
-
@Steven :我相信这个问题与 WeakEvents 正好相反
标签: c# events garbage-collection