更新
我将此处的各种回答结合起来,形成了一个“权威”的答案,并在新问题中进行了发布。
原始问题
在我的代码中,我有一个事件发布器,它存在于整个应用程序的生命周期内(这里简化为基本要素):
public class Publisher
{
//ValueEventArgs<T> inherits from EventArgs
public event EventHandler<ValueEventArgs<bool>> EnabledChanged;
}
由于这个发布者可以在各个地方使用,我为创建这个小助手类而感到非常高兴,以避免在所有订阅者中重写处理代码:
public static class Linker
{
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged += (s, e) => subscriber.Enabled = e.Value;
}
//(Non-lambda version, if you're not comfortable with lambdas)
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged +=
delegate(object sender, ValueEventArgs<bool> e)
{
subscriber.Enabled = e.Value;
};
}
}
在使用较小的机器时,它的表现很好,但偶尔会出现以下问题:
System.ComponentModel.Win32Exception
Not enough storage is available to process this command
事实上,在代码中有一个地方动态创建、添加和删除了订阅控件。鉴于我对垃圾回收等的高级理解(即没有,直到昨天),我从未想过要清理掉自己留下的东西,因为在绝大多数情况下,订阅者也会在应用程序的生命周期内存在。
我已经尝试了一段时间 Dustin Campbell 的 WeakEventHandler,但它 不能与匿名委托一起使用(至少对我来说是这样)。
有没有什么方法可以解决这个问题?我真的很想避免在整个项目中都复制粘贴样板代码。
(哦,不要问我为什么我们总是在创建和销毁控件,那不是我的设计决策……)
(PS:这是一个 Winforms 应用程序,但我们已经升级到 VS2008 和 .Net 3.5,我应该考虑使用 弱事件模式 吗?)
(PPS:来自 Rory 的 好回答,但如果有人能提出一个类似于 WeakEventHandler 的等效方案,避免我必须记住显式 Unlink/Dispose,那就太棒了……)
编辑 我必须承认,我通过 “回收利用” 相关控件来解决这个问题。然而,这个解决方法又让我陷入了麻烦,因为我用的 'key' 显然不是唯一的(哭泣)。我刚刚发现其他链接 这里(尝试过了-看起来有点 太脆弱了-GC会清除委托,即使目标还活着,与下面的s,oɔɯǝɹ答案存在同样的问题),这里(强制你修改发布者,并且不能真正地与匿名委托一起使用),以及这里(由Dustin Campbell称为不完整)。
我想到了一个可能在语义上不可能的解决方法——闭包被设计为“即使我消失了也会留下来”。
我找到了另一个解决方法,所以我会使用它,直到有一个 声音从神那里传来。