wpfui
wpfui copied to clipboard
Memory leak in ListView
Describe the bug
OnLoaded method of the ListView from WPF-UI uses DependencyPropertyDescriptor
to invoke AddValueChanged
, but never unregisters the event handler using RemoveValueChanged
, which leads to a memory leak because a strong refence is created to the component.
https://github.com/lepoco/wpfui/blob/4ac96867797267d566b82fbbfcab0c867353afaa/src/Wpf.Ui/Controls/ListView/ListView.cs#L67-L78
To Reproduce
An instance of a ListView
from WPF-UI stays in memory forever because a strong reference to the component is created and never removed.
public class UnitTest1
{
[Fact]
public Task TestWpfUiControlsListView()
{
return TestListViewMemoryLeakAsync<Wpf.Ui.Controls.ListView>();
}
[Fact]
public Task TestSystemWindowsControlListView()
{
return TestListViewMemoryLeakAsync<System.Windows.Controls.ListView>();
}
public async Task TestListViewMemoryLeakAsync<T>() where T : ListView, new()
{
WeakReference? wr = null;
await StartSTATask(() =>
{
var listView = new T();
wr = new WeakReference(listView);
listView.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent));
listView.RaiseEvent(new RoutedEventArgs(FrameworkElement.UnloadedEvent));
});
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
Assert.NotNull(wr);
Assert.False(wr.IsAlive);
}
private static Task StartSTATask(Action action)
{
var tcs = new TaskCompletionSource<object>();
var thread = new Thread(() =>
{
try
{
action();
tcs.SetResult(new object());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
}
Expected behavior
ListView
should subscribe to Unloaded
event and call RemoveValueChanged
.
Screenshots
No response
OS version
All.
.NET version
All.
WPF-UI NuGet version
3.0.5 - latest (4.0.0-rc.2)
Additional context
No response