Eli*_*eth 44 c# events unsubscribe subscribe
我有3个关于事件的问题:
我有这样的代码:
Ctor:目的:用于数据库属性更新
this.PropertyChanged += (o, e) =>
{
switch (e.PropertyName)
{
case "FirstName": break;
case "LastName": break;
}
};
Run Code Online (Sandbox Code Playgroud)
这个:目的:用于GUI绑定将模型包装到视图模型中
ObservableCollection<Period> periods = _lpRepo.GetDailyLessonPlanner(data.DailyDate);
PeriodListViewModel = new ObservableCollection<PeriodViewModel>();
foreach (Period period in periods)
{
PeriodViewModel periodViewModel = new PeriodViewModel(period,_lpRepo);
foreach (DocumentListViewModel documentListViewModel in periodViewModel.DocumentViewModelList)
{
documentListViewModel.DeleteDocumentDelegate += new Action<List<Document>>(OnDeleteDocument);
documentListViewModel.AddDocumentDelegate += new Action(OnAddDocument);
documentListViewModel.OpenDocumentDelegate += new Action<int, string>(OnOpenDocument);
}
PeriodListViewModel.Add(periodViewModel);
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 55
好吧,让我们先回答最后一个问题.您无法可靠地取消订阅您直接使用lambda表达式订阅的事件.你要么需要与委托(所以你仍然可以使用lambda表达式)围绕保持一个变量或者你需要使用方法组转换代替.
现在至于你是否真的需要取消订阅,这取决于事件生产者和事件消费者之间的关系.如果事件生成者的活动时间比事件消费者长,则应取消订阅 - 因为否则生产者将引用消费者,使其保持活动的时间超过应有的时间.只要生产者生成它,事件处理程序也将继续被调用.
现在在许多情况下这不是问题 - 例如,在一个表单中,引发Click
事件的按钮可能存在的时间与创建它的表单一样长,处理程序通常是订阅的...所以没有必要退订.这对于GUI来说非常典型.
同样,如果您WebClient
仅为单个异步请求创建一个,订阅相关事件并启动异步请求,那么WebClient
当请求完成时,本身将有资格进行垃圾回收(假设您没有在其他地方保留引用) ).
基本上,您应该始终考虑生产者和消费者之间的关系.如果制作人的寿命比您希望消费者的寿命长,或者在您不再对此感兴趣后继续提升该事件,那么您应该取消订阅.
Vla*_*lad 30
1)这取决于.通常这是一个好主意,但有一些典型的情况你不需要.基本上,如果您确定订阅对象将比事件源更长,那么您应该取消订阅,否则会产生不必要的引用.
但是,如果您的对象正在订阅自己的事件,请执行以下操作:
<Window Loaded="self_Loaded" ...>...</Window>
Run Code Online (Sandbox Code Playgroud)
- 然后你不必.
2)订阅事件会额外引用订阅对象.因此,如果您不取消订阅,您的对象可能会通过此引用保持活动,从而有效地进行内存泄漏.通过取消订阅,您将删除该引用.请注意,在自我订阅的情况下,不会出现问题.
3)你可以这样做:
this.PropertyChanged += PropertyChangedHandler;
...
this.PropertyChanged -= PropertyChangedHandler;
Run Code Online (Sandbox Code Playgroud)
哪里
void PropertyChangedHandler(object o, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "FirstName": break;
case "LastName": break;
}
}
Run Code Online (Sandbox Code Playgroud)
当正在订阅的实例与正在订阅的实例具有相同的范围时,您不必取消订阅事件。
假设您是一个表单并且您正在订阅一个控件,这两个一起形成一个组。但是,如果您有一个管理表单的中心类,并且您订阅Closed
了该表单的事件,则它们不会形成一个组,一旦表单关闭,您必须取消订阅。
订阅事件会使订阅的实例创建对正在订阅的实例的引用。这可以防止垃圾收集。因此,当您有一个管理表单实例的中央类时,这会将所有表单保存在内存中。
WPF 是一个例外,因为它具有弱事件模型,其中使用弱引用订阅事件,并且不会将表单保存在内存中。但是,当您不是表单的一部分时,取消订阅仍然是最佳做法。
归档时间: |
|
查看次数: |
35898 次 |
最近记录: |