Насколько я понимаю, подписчику (потребителю) события всегда грозит утечка (если производитель живет дольше). Если я подпишусь на (нестатическое) событие с помощью анонимной лямбда-функции внутри статического метода, мне не нужно будет отписываться, если я хочу, чтобы лямбда оставалась в живых до тех пор, пока живет производитель?
Существует вариант вопроса (Создает ли подписка на лямбда-события утечку памяти?) С этим ответом , цитируя:
Кроме того, лямбда-выражение не используетлюбые переменные из этого, так что это, вероятно, будет реализовано статическим методом без цели в любом случае ... Я предполагаю, что реальная ситуация, в которой вы заинтересованы, имеет более интересное лямбда-тело.
Я интерпретируюэто означает, что вам, возможно, придется отказаться от подписки, если лямбда-выражение использует переменные из цели (this
), но в статическом методе this
не существует, поэтому возникает вопрос.
Конкретныйкод, о котором я думаю, взят из этого ответа (см. ниже). Комментарии к этому ответу предполагают, что вы должны отказаться от подписки, чтобы избежать утечек памяти, но так ли это на самом деле? Что именно просочилось? Другой ответ на тот же вопрос, который пытался обработать отмену подписки, вместо этого фактически добавил потенциальную утечку памяти (сохраняя обработчики событий в статическом словаре, который не может быть очищен).
private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = source as DataGrid;
ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
// There should be no need to unsubscribe to e.OldValue?
dataGrid.Columns.Clear();
if (columns == null)
{
return;
}
foreach (DataGridColumn column in columns)
{
dataGrid.Columns.Add(column);
}
// This event handler will not keep the columns alive, and the lambda will only be alive as long as the columns is alive?
columns.CollectionChanged += (sender, e2) =>
{
NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
if (ne.Action == NotifyCollectionChangedAction.Reset)
{
// Clear dataGrid.Columns
...
}
else if (ne.Action == NotifyCollectionChangedAction.Add)
{
// Add to dataGrid.Columns
...
}
else if (ne.Action == NotifyCollectionChangedAction.Move)
{
...
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
...
}
else if (ne.Action == NotifyCollectionChangedAction.Replace)
{
...
}
};
}