在c#中使用按钮后,我是否必须取消订阅按钮事件
本文关键字:按钮 取消 事件 是否 | 更新日期: 2023-09-27 18:03:30
我使用的是windows窗体。
我的C#应用程序包含100个user controls
。我在需要的时候一次显示/隐藏这100个user controls
中的一个,并隐藏其余的。这些user controls
中的每一个都有30个buttons
,我在构造函数中订阅了button
事件,如下所示:
public UserControl1()
{
InitializeComponent();
button1.Click += new EventHandler(MyButtonClick);
button2.Click += new EventHandler(MyButtonClick);
.
.
button30.Click += new EventHandler(MyButtonClick);
}
void MyButtonClick(object sender, EventArgs e)
{
// do something
}
因此,当我运行应用程序时,所有100个User controls
都订阅了30个buttons
事件,一些user controls
订阅了该事件,但在应用程序的使用过程中从未使用过它们。
我在这里和这里读到了一些关于取消订阅事件的内容,但有些答案说你应该取消订阅,因为这会导致内存泄漏,有些答案说不必,因此答案仍然不清楚。
我的问题是,使用button
事件后是否必须取消订阅,例如:当我显示/隐藏user control
时。如果是,当显示user control
时如何订阅button
事件,当未显示时如何取消订阅。
为什么取消订阅
它归结为订阅者(UserControl(与订阅(Button(相比的使用寿命。订阅包含对订阅服务器的引用。因此,如果订阅的使用寿命更长,那么订阅的内存就会泄漏给订阅。
因此,在您的情况下,您应该询问按钮是否会比UserControl持续更长时间。如果按钮的使用寿命较短,则无需取消订阅。否则,您将内存泄漏UserControl。
在你的情况下,我想你不需要取消订阅。
如果我答对了你的问题-每个控件只订阅它自己的子控件(30个按钮(。当忘记取消订阅是个坏主意时,发布者(按钮(的寿命将比订阅者(用户控件(长。为什么?因为发布者将存储到订阅服务器的链接,并将阻止该订阅服务器被垃圾回收器处理在您的情况下,按钮的寿命永远不会超过它的父用户控件,所以您不需要取消订阅
在您的情况下,没有理由担心。你链接到的两个例子有一个不同的"种类"事件,如下所示:如果对象a发生了变化,那么应该调用方法X,这样X就可以对对象a中的变化进行操作或处理。例如,A=产品的库存;如果A的计数为零,那么它就不能再出售,或者必须订购新的物品,等等。
当响应更改的数据时,调用X的需求可能会在某个时间点停止,然后注销事件可能会很有益,尤其是在没有其他方法中断或禁用链接的情况下。
然而,在像您这样的用户界面场景中,通常仍然需要调用X。如果需要,可以通过另一种方式控制它,例如禁用按钮或隐藏按钮。在按钮和方法之间建立链接确实没有什么代价。断开链接的唯一原因是"如果点击按钮,我不想再叫X了"。
您通常不必取消订阅事件。也就是说,在特殊情况下,需要这样做。
这通常看起来是这样的:您有一个长寿命对象,它创建长寿命对象并附加它们的方法来处理其(或其他一些长寿命对象的(事件。或者,可以创建一个对象,并将其方法附加到寿命更长的不同对象的事件。
现在,当这些短寿命对象超出范围时,它们仍然会附加到事件,因此只要长寿命对象(它们订阅到的事件(在范围内,Garbage Collector
就不会回收它们。这是因为它保留了它们对应该处理其事件的对象的引用。
在您的情况下(以及大多数其他典型情况下(,处理程序是拥有子控件的类的成员,因此不存在人为延长任何对象的生存期的风险。您不需要在此处明确取消订阅。
您实际上不必取消订阅,但您应该取消订阅。取消订阅的方式是:
//adding
EventHandler myHandler = new EventHandler(MyButtonClick);
button1.Click += myHandler;
//removing
button1.Click -= myHandler;