ReactiveUI ViewModel 内存泄漏
ReactiveUI ViewModel memory leak
我在内存泄漏方面遇到了非常奇怪的问题,经过长时间的测试、调试和 trial/error 尝试后我找不到源代码。
内存泄漏的根源是根据主题的推送重新加载对象。我在哪一部分加载当前数据库值并将其添加到 SourceCache。
这部分正在获取推送,以启动重新加载
this.databaseSignalRClient
.UpdatedObservable<JobLine>()
.WhereNotNull()
.Where(x => JobLinesCache.Lookup(x.Id).HasValue)
.SelectMany(LoadJobLine)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(jl => JobLinesCache.AddOrUpdate(jl));
这里有 LoadJobLine 函数
private async Task<JobLine> LoadJobLine(DbNotification dbNotification)
{
using var repo = Locator.Current.GetService<IWmsRepository>();
return await repo.Job.JobLineRepository.FindAsync(dbNotification.Id);
}
这就是我向 UI 提供 ViewModels 的方式:
private readonly ReadOnlyObservableCollection<JobLineViewModel> jobLineViewModels;
public ReadOnlyObservableCollection<JobLineViewModel> JobLineViewModels => jobLineViewModels;
JobLinesCache.Connect()
.SortBy(jl => jl.CaseNo)
.Transform(jl => new JobLineViewModel(jl))
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out jobLineViewModels)
.Subscribe();
这是创建的 ViewModel:
public class JobLineViewModel : ReactiveObject
{
public JobLineViewModel(
JobLine jobLine
)
{
JobLine = jobLine;
}
[Reactive]
public JobLine JobLine { get; private set; }
[Reactive]
public string ContainingItemsString { get; private set; }
}
最后将集合绑定到 UI:
this.WhenActivated(d =>
{
this.OneWayBind(ViewModel, vm => vm.JobLineViewModels, v => v.TestIC.ItemsSource)
.DisposeWith(d);
});
我确实测试了虚拟化堆栈面板和没有。
<ItemsControl x:Name="TestIC">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
还有这个问题。 JobLineViewModel 由于某种原因没有得到垃圾收集。我通过每 10 毫秒 ping 一次 signalR 更新来模拟它。
我真的不知道是什么让 JobLineView 保持活力。我也可以 post 它的代码,但我没有看到任何问题...:[=26=]
<rx:ReactiveUserControl x:Class="Mtc.UserControls.JobLineView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Mtc.UserControls"
mc:Ignorable="d"
x:TypeArguments="vm:JobLineViewModel"
xmlns:rx="http://reactiveui.net"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:vm="clr-namespace:Wms.Mtc.ViewModels;assembly=Wms.Mtc"
d:DesignHeight="450" d:DesignWidth="800">
<md:Card Margin="20,10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Viewbox Margin="10">
<TextBlock x:Name="CaseNo_TextBlock" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Viewbox>
<Grid Margin="10" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Text="D01 D01-020-0B-21" Grid.Row="0" HorizontalAlignment="Center" />
<!--<md:PackIcon Kind="ArrowBottom" Grid.Row="1" HorizontalAlignment="Center" Width="45" Height="45" />-->
<TextBlock Text="D09" Grid.Row="2" HorizontalAlignment="Center" />
</Grid>
</Grid>
<TextBlock x:Name="Items_TextBlock" FontSize="28" HorizontalAlignment="Center" Margin="5" Grid.Row="1" />
</Grid>
</md:Card>
</rx:ReactiveUserControl>
和后面的代码:
public partial class JobLineView : ReactiveUserControl<JobLineViewModel>
{
public JobLineView()
{
InitializeComponent();
this.WhenActivated(d =>
{
this.OneWayBind(ViewModel, vm => vm.JobLine, v => v.CaseNo_TextBlock.Text, jl=>jl.CaseNo)
.DisposeWith(d);
/* this.OneWayBind(ViewModel, vm => vm.JobLine.Status, v => v.CaseNo_TextBlock.Foreground, status=> JobLineStatusToBrushConverter.Instance.Convert(status,null,null,null))
.DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.JobLine, v => v.Items_TextBlock.Text, jl=> JobLineToItemsStringConverter.Instance.Convert(jl, null,null,null))
.DisposeWith(d);*/
});
}
}
如有任何想法,我将不胜感激。这个真的很棘手,我不知道怎么解决。
我还添加了托管内存的屏幕截图:
谢谢
-----编辑
我确实剥离了所有内容的整个视图,以避免 MaterialDesign 中的潜在问题:
但问题仍然存在,一定是 Reactive 的问题UI,但是...
这也是 JobLine class,正在传递给 VM:
public class JobLine : ReactiveObject
{
[Reactive]
public string CaseNo { get; set; }
[Reactive]
public decimal? CreatedBy { get; set; }
[Reactive]
public DateTime? CreatedDate { get; set; }
[Reactive]
public string FromInventory { get; set; }
[Reactive]
public string FromLocator { get; set; }
[Reactive]
public decimal Id { get; set; }
[Reactive]
public decimal? JobHeaderId { get; set; }
[Reactive]
public decimal? MachineId { get; set; }
[Reactive]
public decimal? PickingOrder { get; set; }
[Reactive]
public decimal? Printed { get; set; }
[Reactive]
public decimal? RoutingId { get; set; }
[Reactive]
public decimal? SourceLineId { get; set; }
[Reactive]
public decimal? Status { get; set; }
[Reactive]
public string ToInventory { get; set; }
[Reactive]
public string ToLocator { get; set; }
[Reactive]
public decimal? UpdatedBy { get; set; }
[Reactive]
public DateTime? UpdatedDate { get; set; }
[Reactive]
public decimal? Valid { get; set; }
[Reactive]
public string WindowsUser { get; set; }
}
在消除所有可能的因素后(剥离视图和视图模型中的任何绑定,或 material 设计内容(图标)等)问题仍然存在。某些东西与 ViewModel 一起使 View 在内存中保持活动状态。虽然不再在视觉树中。
欢迎提出任何想法。
错误已在库存储库中报告并修复:
https://github.com/reactiveui/ReactiveUI/issues/3091
我在内存泄漏方面遇到了非常奇怪的问题,经过长时间的测试、调试和 trial/error 尝试后我找不到源代码。
内存泄漏的根源是根据主题的推送重新加载对象。我在哪一部分加载当前数据库值并将其添加到 SourceCache。
这部分正在获取推送,以启动重新加载
this.databaseSignalRClient
.UpdatedObservable<JobLine>()
.WhereNotNull()
.Where(x => JobLinesCache.Lookup(x.Id).HasValue)
.SelectMany(LoadJobLine)
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(jl => JobLinesCache.AddOrUpdate(jl));
这里有 LoadJobLine 函数
private async Task<JobLine> LoadJobLine(DbNotification dbNotification)
{
using var repo = Locator.Current.GetService<IWmsRepository>();
return await repo.Job.JobLineRepository.FindAsync(dbNotification.Id);
}
这就是我向 UI 提供 ViewModels 的方式:
private readonly ReadOnlyObservableCollection<JobLineViewModel> jobLineViewModels;
public ReadOnlyObservableCollection<JobLineViewModel> JobLineViewModels => jobLineViewModels;
JobLinesCache.Connect()
.SortBy(jl => jl.CaseNo)
.Transform(jl => new JobLineViewModel(jl))
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out jobLineViewModels)
.Subscribe();
这是创建的 ViewModel:
public class JobLineViewModel : ReactiveObject
{
public JobLineViewModel(
JobLine jobLine
)
{
JobLine = jobLine;
}
[Reactive]
public JobLine JobLine { get; private set; }
[Reactive]
public string ContainingItemsString { get; private set; }
}
最后将集合绑定到 UI:
this.WhenActivated(d =>
{
this.OneWayBind(ViewModel, vm => vm.JobLineViewModels, v => v.TestIC.ItemsSource)
.DisposeWith(d);
});
我确实测试了虚拟化堆栈面板和没有。
<ItemsControl x:Name="TestIC">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
还有这个问题。 JobLineViewModel 由于某种原因没有得到垃圾收集。我通过每 10 毫秒 ping 一次 signalR 更新来模拟它。
我真的不知道是什么让 JobLineView 保持活力。我也可以 post 它的代码,但我没有看到任何问题...:[=26=]
<rx:ReactiveUserControl x:Class="Mtc.UserControls.JobLineView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Mtc.UserControls"
mc:Ignorable="d"
x:TypeArguments="vm:JobLineViewModel"
xmlns:rx="http://reactiveui.net"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:vm="clr-namespace:Wms.Mtc.ViewModels;assembly=Wms.Mtc"
d:DesignHeight="450" d:DesignWidth="800">
<md:Card Margin="20,10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Viewbox Margin="10">
<TextBlock x:Name="CaseNo_TextBlock" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Viewbox>
<Grid Margin="10" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Text="D01 D01-020-0B-21" Grid.Row="0" HorizontalAlignment="Center" />
<!--<md:PackIcon Kind="ArrowBottom" Grid.Row="1" HorizontalAlignment="Center" Width="45" Height="45" />-->
<TextBlock Text="D09" Grid.Row="2" HorizontalAlignment="Center" />
</Grid>
</Grid>
<TextBlock x:Name="Items_TextBlock" FontSize="28" HorizontalAlignment="Center" Margin="5" Grid.Row="1" />
</Grid>
</md:Card>
</rx:ReactiveUserControl>
和后面的代码:
public partial class JobLineView : ReactiveUserControl<JobLineViewModel>
{
public JobLineView()
{
InitializeComponent();
this.WhenActivated(d =>
{
this.OneWayBind(ViewModel, vm => vm.JobLine, v => v.CaseNo_TextBlock.Text, jl=>jl.CaseNo)
.DisposeWith(d);
/* this.OneWayBind(ViewModel, vm => vm.JobLine.Status, v => v.CaseNo_TextBlock.Foreground, status=> JobLineStatusToBrushConverter.Instance.Convert(status,null,null,null))
.DisposeWith(d);
this.OneWayBind(ViewModel, vm => vm.JobLine, v => v.Items_TextBlock.Text, jl=> JobLineToItemsStringConverter.Instance.Convert(jl, null,null,null))
.DisposeWith(d);*/
});
}
}
如有任何想法,我将不胜感激。这个真的很棘手,我不知道怎么解决。
我还添加了托管内存的屏幕截图:
谢谢
-----编辑
我确实剥离了所有内容的整个视图,以避免 MaterialDesign 中的潜在问题:
但问题仍然存在,一定是 Reactive 的问题UI,但是...
这也是 JobLine class,正在传递给 VM:
public class JobLine : ReactiveObject
{
[Reactive]
public string CaseNo { get; set; }
[Reactive]
public decimal? CreatedBy { get; set; }
[Reactive]
public DateTime? CreatedDate { get; set; }
[Reactive]
public string FromInventory { get; set; }
[Reactive]
public string FromLocator { get; set; }
[Reactive]
public decimal Id { get; set; }
[Reactive]
public decimal? JobHeaderId { get; set; }
[Reactive]
public decimal? MachineId { get; set; }
[Reactive]
public decimal? PickingOrder { get; set; }
[Reactive]
public decimal? Printed { get; set; }
[Reactive]
public decimal? RoutingId { get; set; }
[Reactive]
public decimal? SourceLineId { get; set; }
[Reactive]
public decimal? Status { get; set; }
[Reactive]
public string ToInventory { get; set; }
[Reactive]
public string ToLocator { get; set; }
[Reactive]
public decimal? UpdatedBy { get; set; }
[Reactive]
public DateTime? UpdatedDate { get; set; }
[Reactive]
public decimal? Valid { get; set; }
[Reactive]
public string WindowsUser { get; set; }
}
在消除所有可能的因素后(剥离视图和视图模型中的任何绑定,或 material 设计内容(图标)等)问题仍然存在。某些东西与 ViewModel 一起使 View 在内存中保持活动状态。虽然不再在视觉树中。
欢迎提出任何想法。
错误已在库存储库中报告并修复: https://github.com/reactiveui/ReactiveUI/issues/3091